3

I am trying to sort an array of words in Ruby 1.8.7 by an insane set of rules. This can be simplified to wanting to sort case-insensitive .sort_by{|a| a.downcase} then re-sort case-sensitive but only if the 2 strings are the same.

I would think you could just .downcase compare only the strings that are equal and then sort just those, sending 0 for the rest. But no, that isn't working for me.

Here's what I have:

["A", "a", "a.", "A.", "Ba", "ba"].sort_by{|a| a.downcase}.sort{|a,b| a.downcase==b.downcase ? a<=>b : 0 }

Desired output:

["A", "a", "A.", "a.", "Ba", "ba"]

Thanks for your help.

1 Answer 1

4

If a.downcase == b.downcase then you want to sort using a case-sensitive comparison, right? That really means that you want to sort by the pair [a.downcase, a] and arrays in Ruby compare element by element so you just want:

array.sort_by { |s| [ s.downcase, s ] }

Suppose sort_by is comparing two arrays a1 and a2 to see which one goes first. That's just an a1 <=> a2 call. If a1[0] != a2[0] then the spaceship operator won't have to look at the second elements of the arrays to break a tie because there is no tie and <=> can return +1 or -1 right away. If a1[0] == a2[0] then a1[0] <=> a2[0] is 0 and the spaceship has to look at the second elements to see how to break the tie (or leave the tie as-is if a1 == a2). That sounds like the comparison logic you're after.

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

3 Comments

Where 𝝁 says " ...and arrays in Ruby compare element by element..." that is explained more fully in the doc for Arrays#<=>. To carry this one step further, If you (the OP) wanted to sort first on s downcased, then sort ties on the length of s, longest first, then sort ties of both s.downcase and s.size by s, you could sort on the array [s.downcase, -s.size, s].
Using an array to sort by multiple conditions is an idea I hadn't seen before. This is very helpful.
This is a great answer to the question. Exactly the answer I needed for the question I posed, so thank you. I have to add that I'm torn because I posted this to try to fix my a.downcase==b.downcase approach, instead your answer made me perfectly rethink my question in the way I needed to get the job done, so I will happily give you the checkmark. Unfortunately, now this question feels like a duplicate to all these: google.com/#q=ruby+sort+by+multiple+site:stackoverflow.com and for that I apologize to anyone who eventually marks this question as a duplicate.

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.