From: Steve Howell Date: 2010-10-15T10:10:19+09:00 Subject: Re: sort_by: multiple fields with reverse sort On Oct 14, 1:25 pm, Ryan Davis wrote: > On Oct 14, 2010, at 08:35 , Steve Howell wrote: > > >  module Enumerable > >    def sort_by_multi(*key_methods) > >      def compare(a,b, key_methods) > > This doesn't do what you think (or at least imply that) it does. Care to explain? puts a.sort_by_multi( [Proc.new { |a| a[0] }], [Proc.new { |a| a[1] }, :desc] ).inspect $ ruby foo.rb [["archie", 20, 5], ["newton", 10, 3], ["radio", 40, 5], ["radio", 30, 5], ["radio", 20, 5]] $ cat foo.rb module Enumerable def sort_by_multi(*key_methods) # allow for multiple key_methods and only # evaluate them when they are truly needed # for the sort def compare(a,b, key_methods) i = 0 while i < key_methods.size do for elem in [a, b] do key = elem[1] if elem[0].size <= i elem[0] << key_methods[i][0].call(key) end end if key_methods[i][1] == :desc a, b = b, a end result = (a[0][i] <=> b[0][i]) return result unless result == 0 i += 1 end return result end self.collect do |item| [ [], item ] end.sort do |a, b| compare(a, b, key_methods) end.collect do |kv| kv[1] end end end a = [ ["radio", 30, 5], ["radio", 40, 5], ["radio", 20, 5], ["archie", 20, 5], ["newton", 10, 3] ] puts a.sort_by_multi( [Proc.new { |a| a[0] }], [Proc.new { |a| a[1] }, :desc] ).inspect