3

I have an array that must be sorted with low number to high number and then alphabetical order. Must use Array#sort_by

 i_want_dogs = ["I", "want", 5, "dogs", "but", "only", "have", 3]

I want it to output:

 => [3,5,"I","but","dogs","have","only","want"]

I tried:

 i_want_dogs.sort_by {|x,y| x <=> y }

I know that is obviously wrong, but I can't figure it out with the integers and the strings combined.

5
  • Have you looked at the documentation for Enumerable#sort_by? Commented Aug 6, 2014 at 21:39
  • Dumb question but do you need them in strings AND ints? :D Commented Aug 6, 2014 at 21:42
  • I did, but still cannot figure it out. I was thinking maybe I had to convert the integers to chr then everything to a number and sort it like that inside the block, or something like that, but I cannot get the syntax right. Commented Aug 6, 2014 at 21:45
  • @limelights - yeah, I need it to output exactly as shown above Commented Aug 6, 2014 at 21:46
  • 1
    Its interesting that the capital I is before the other words. i_want_dogs.sort_by { |x, y| y.to_i <=> x.to_i } should get you pretty close, but the "I" is at the end. Commented Aug 6, 2014 at 22:00

4 Answers 4

5

Use the sort method with a block that defines a comparator that does what you want. I wrote a simple one that compares values when the classes are the same and class names when they are different.

def comparator(x, y)
  if x.class == y.class
    return x <=> y
  else
    return x.class.to_s <=> y.class.to_s
  end
end

Use it like this:

i_want_dogs.sort { |x, y| comparator(x, y) }
Sign up to request clarification or add additional context in comments.

Comments

3

Use partition to separate numbers from strings, sort each separately and join the final result, e.g.

i_want_dogs.partition { |i| i.is_a?(Fixnum) }.map(&:sort).flatten

Comments

2

This will give you the result:

i_want_dogs.sort_by {|x| x.to_s }

UPDATE:

Thanks @vacawama who points out that it will sort numbers alphabetically. If you need to sort number by it's value, other answers will be something you need to try.

5 Comments

That's exactly what I was looking for. Others kept using different methods, but it was required for me to use sort_by. Thank you +1
+1 Very clever solution! We can also add downcase should it be case-insensitive, e.g. x.to_s.downcase
@vacawama - it sorted them correctly on the test I did, but I didn't do numerous tests.
This won't sort your numbers correctly, if you care about that. Numbers are sorted "alphabetically" instead of numerically. eg. [3, 32, 355, 4, 500] is sorted "alphabetically".
@vacawama You are correct. Looks it's kind of a small ruby exercise to try sort_by for this test case. If it really needs numbers sorted,your answer and others will be something he can try.
2

First you need to convert the elements in the array to a string. Try this

i_want_dogs.sort_by(&:to_s)

This will return

[3,5,"I", "but", "dogs", "have", "only" "want"]

Comments

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.