From: Steve Howell Date: 2010-10-14T11:20:12+09:00 Subject: Re: sort_by: multiple fields with reverse sort On Oct 13, 5: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} > I definitely feel that sort_by has a compelling advantage over sort for any large-ish dataset involving keys with nontrivial transformations from the original object. You obviously want to avoid doing NlogN transformations when N would suffice. Does Ruby's sort_by method guarantee a stable sort? If it does, then you could do sort_by the first field (reversing as needed), then sort_by the second field (reversing as needed), then sort_by the third field (reversing as needed), and so on. Doing M sort passes on 1 key is no less efficient than doing 1 sort pass on M keys, except to the extent that the latter maybe short-circuits a few comparisons. At worst you are talking an M-ish difference that is mostly dwarfed by NlogN. Your essential underlying question about representing the "inverse" of a key is pretty intriguing. I don't know of any general way to solve that problem, other than encapsulating it in a class, as has been suggested.