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.
> Thx, rahul.
>

It would be nice if Ruby supported a sort_by on steroids.

  sorted_list =3D list.multi_field_sort_by(
    { |x| x.department.name },
    { |x| x.position.name },
    desc { |x| x.level },
    desc { |x| x.salary ? x.salary : x.rate * db_lookup(x,
'hours_worked') }
  )

I believe you could write a decent multi_field_sort_by in Ruby that
would be efficient for large enough lists to outperform more tedious
approaches, but it would be even better if Ruby natively supported it.

My proposed syntax might be slightly off, but you get the idea.  You'd
pass a list of blocks that represent the successive tiebreakers, and
multi_field_sort_by would presumably cache the results from each
transformation, evaluating the blocks only as necessary.  The "desc"
thingy would actually produce some kind of wrapper that
multi_field_sort_by could introspect to know that it needs to apply a
particular tiebreaker in reverse order.