From: Stefano Crocco Date: 2010-10-13T17:10:51+09:00 Subject: Re: sort_by: multiple fields with reverse sort On Wednesday 13 October 2010, Rahul Kumar wrote: > |I need to use *sort_by* to sort a table, since the user could select > |columns in any order. > | > | b=[ ["radio", 30, 5], ["radio", 20, 5], ["archie", 20, 5], > |["newton", 10, 3] ] > | b.sort_by{|x| [ x[1], x[0] ]} > | > |Works fine. However, often the user will want a reverse sort on some > |field. I do not off-hand know the datatype of the field, but in most > |cases it will be a String. > | > |I tried: > | > | b.sort_by{|x| [ !x[1] ]} > |This works (one criteria), but this does not: > | b.sort_by{|x| [ !x[1], x[0] ]} > | > |Another thread here, suggested using a minus for Numbers but what about > |Strings. > |Thx, rahul. Are you sure the one criterium version works as you think? !x[1] returns a boolean value (true if x[1] is false or nil and false otherwise). So, if the contents of the arrays are all strings or numbers, it'll compare items by comparing equal arrays only containing the element false. Most likely, this would give you the elements in the same order. I don't know how to do what you want using sort_by, but you can do that using sort. For example, the following code does a reverse sort on the 1 index and a normal sort on the 0 index b.sort do |a, b| res = -(a[1] <=> b[1]) res = a[0] <=> b[0] if res == 0 res end For more information, look at the documentation for Enumerable#sort and the Comparable module (for the <=> operator). I hope this helps Stefano