On Oct 13, 12:46=A0am, Rahul Kumar <sentinel1... / gmail.com> wrote: > I need to use *sort_by* to sort a table, since the user could select > columns in any order. > > =A0 =A0 b=3D[ ["radio", 30, 5], ["radio", 20, 5], ["archie", 20, 5], > ["newton", 10, 3] ] > =A0 =A0 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: > > =A0 =A0 b.sort_by{|x| [ !x[1] ]} > This works (one criteria), but this does not: > =A0 =A0 b.sort_by{|x| [ !x[1], x[0] ]} > > Another thread here, suggested using a minus for Numbers but what about > Strings. Here is a solution that allows you to lazily evaluate keys and specify that certain keys are to be reversed. module Enumerable def sort_by(*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 =3D 0 while i < key_methods.size do for elem in [a, b] do fields =3D elem[0] key =3D elem[1] if fields.size <=3D i fields[i] =3D key_methods[i][0].call(key) end end if key_methods[i][1] =3D=3D :desc a, b =3D b, a end result =3D (a[0][i] <=3D> b[0][i]) return result unless result =3D=3D 0 i +=3D 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 =3D [ ["radio", 30, 5], ["radio", 40, 5], ["radio", 20, 5], ["archie", 20, 5], ["newton", 10, 3] ] puts a.sort_by( [Proc.new { |a| a[0] }], [Proc.new { |a| a[1] }, :desc] ).inspect