From: Rob Biedenharn Date: 2010-10-13T22:58:45+09:00 Subject: Re: sort_by: multiple fields with reverse sort On Oct 13, 2010, at 8:53 AM, Rahul Kumar wrote: > When i sat down to code, i realized that i could not just put the > sort_keys list to sort_by, i would have to unroll the sort_keys array. > So, i might as well use sort. This seems to work in the small case i > have. Could someone comment on this, and suggest cleaner better way to > do. Thanks. > > b=[ ["radio", 30, 5], ["radio", 20, 5], ["archie", 20, 5], ["newton", > 10, 3] ] > sort_keys=[1,0] > rev_flag = [true, false] > > c=b.sort{|x,y| > res = 0 > sort_keys.each_with_index { |e,i| > if rev_flag[i] > res = y[e] <=> x[e] > else > res = x[e] <=> y[e] > end > break if res != 0 > } > res > } > c > > -- > Posted via http://www.ruby-forum.com/. > While it is not strictly equivalent to array_of_strings.sort.reverse, this little addition to String allows array_of_strings.sort_by{|s|-s} class String RAB_REPLACE = ('a'..'z').to_a.reverse.join.freeze def -@ self.tr('a-z',RAB_REPLACE) end end Then you can do: b.sort_by {|ary| [ary[1], -ary[0]] } irb> b.sort_by {|ary| [ary[1], -ary[0]] } => [["newton", 10, 3], ["radio", 20, 5], ["archie", 20, 5], ["radio", 30, 5]] If your strings are always simple words, then this may be enough for you (or at least give you an idea). If your array is short (i.e., the difference between sort and sort_by is acceptable), then you can always do: irb> b.sort {|e1,e2| (e1[1] <=> e2[1]).nonzero? || e2[0] <=> e2[0] } => [["newton", 10, 3], ["radio", 20, 5], ["archie", 20, 5], ["radio", 30, 5]] ( which doesn't rely on String#-@ ) -Rob Rob Biedenharn Rob@AgileConsultingLLC.com http://AgileConsultingLLC.com/ rab@GaslightSoftware.com http://GaslightSoftware.com/