Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I sort by multiple conditions with different orders?

Tags:

sorting

ruby

I'd really like to handle this without monkey-patching but I haven't been able to find another option yet.

I have an array (in Ruby) that I need to sort by multiple conditions. I know how to use the sort method and I've used the trick on sorting using an array of options to sort by multiple conditions. However, in this case I need the first condition to sort ascending and the second to sort descending. For example:

ordered_list = [[1, 2], [1, 1], [2, 1]]

Any suggestions?

Edit: Just realized I should mention that I can't easily compare the first and second values (I'm actually working with object attributes here). So for a simple example it's more like:

ordered_list = [[1, "b"], [1, "a"], [2, "a"]]
like image 542
PJ. Avatar asked Sep 16 '08 14:09

PJ.


2 Answers

How about:


ordered_list = [[1, "b"], [1, "a"], [2, "a"]]
ordered_list.sort! do |a,b|
  [a[0],b[1]] <=> [b[0], a[1]]
end

like image 66
Brian Phillips Avatar answered Sep 20 '22 15:09

Brian Phillips


I was having a nightmare of a time trying to figure out how to reverse sort a specific attribute but normally sort the other two. Just a note about the sorting for those that come along after this and are confused by the |a,b| block syntax. You cannot use the {|a,b| a.blah <=> b.blah} block style with sort_by! or sort_by. It must be used with sort! or sort. Also, as indicated previously by the other posters swap a and b across the comparison operator <=> to reverse the sort order. Like this:

To sort by blah and craw normally, but sort by bleu in reverse order do this:

something.sort!{|a,b| [a.blah, b.bleu, a.craw] <=> [b.blah, a.bleu, b.craw]}

It is also possible to use the - sign with sort_by or sort_by! to do a reverse sort on numerals (as far as I am aware it only works on numbers so don't try it with strings as it just errors and kills the page).

Assume a.craw is an integer. For example:

something.sort_by!{|a| [a.blah, -a.craw, a.bleu]}
like image 44
TwoByteHero Avatar answered Sep 19 '22 15:09

TwoByteHero