0

Right now I've produced the following code to sort a list of domains

domains = [
  'api.test.google.com',
  'dev.blue.google.com',
  'dev.test.google.com',
  'a.blue.google.com'
]

filtered = []

domains.each { |domain| filtered.push domain.reverse! }
domains.sort!
domains.each { |domain| filtered.push domain.reverse! }

The output of this code will be:

["a.blue.google.com", "dev.blue.google.com", "api.test.google.com", "dev.test.google.com"]

I'm trying to find a way to make this more elegant as it does not look like the most optimal solution to solve this problem but I'm having issues figuring out what is.

Thank you for your help!

0

2 Answers 2

3

Would this work for you?

domains.
  map{|d| d.split(".")}.
  sort_by(&:reverse).
  map{|d| d.join(".") }

Edit: or indeed

domains.sort_by{|x| x.split(".").reverse}

Just to add, I think that something like this deserves to be a value object, as these are not simply strings and they have their own attributes and special behaviour (such as this sort).

For example:

class Domain
  include Comparable

  def initialize(string)
    @string = string
  end

  def to_s
    @string
  end

  def elements
    @string.split(".")
  end

  protected def <=>(other)
    elements.reverse <=> other.elements.reverse
  end

  def tld
    elements.last
  end
end

So you can then:

domains = [
  Domain.new('api.test.google.com'),
  Domain.new('dev.blue.google.com'),
  Domain.new('dev.test.google.com'),
  Domain.new('a.blue.google.com'),
]

domains.map(&:to_s)
 => ["api.test.google.com", "dev.blue.google.com", "dev.test.google.com", "a.blue.google.com"] 

domains.sort.map(&:to_s)
 => ["a.blue.google.com", "dev.blue.google.com", "api.test.google.com", "dev.test.google.com"] 

You can also add in any other behaviour you like, such as a method for returning the top level domain.

Sign up to request clarification or add additional context in comments.

Comments

3

If all you want to do is sort by the reversed value use sort_by:

domains = [
  'api.test.google.com',
  'dev.blue.google.com',
  'dev.test.google.com',
  'a.blue.google.com'
]

domains.sort_by { |domain| domain.reverse }

#=> ["a.blue.google.com", "dev.blue.google.com", "api.test.google.com", "dev.test.google.com"]

If you are concerned with keeping the strings between the dots in the original order you can use:

domains.sort_by { |domain| domain.split('.').reverse }

#=> ["a.blue.google.com", "dev.blue.google.com", "api.test.google.com", "dev.test.google.com"]

2 Comments

...or domains.sort_by(&:reverse).
It's just a coincidence that reversing the strings for sorting works with these domains. Try to sort ['az.com', 'by.com', 'cx.com']. It also doesn't take the hierarchy into account.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.