On Thu, Jan 19, 2012 at 8:58 AM, Garthy D
<garthy_lmkltybr / entropicsoftware.com> wrote:
> Hi all,
>
> I've found that for the current project I am working on that I am frequen=
tly
> doing sorts based on multiple keys. The comparisons on each key tend to
> vary, ie. sometimes I want descending rather than ascending, and other ti=
mes
> the comparison itself is complex.
>
> I usually do something like this:
>
> foo.sort! {|a,b|
> =A0# Ascending, primary.
> =A0rv =3D a.key0 <=3D> b.key0
> =A0# Descending, secondary.
> =A0rv =3D b.key1 <=3D> a.key1 if rv =3D=3D 0
> =A0# A tricky and expensive comparison, tertiary.
> =A0rv =3D a.magic(b) if rv =3D=3D 0
> =A0rv
> }
>
> Does anyone have any suggestions as to a more elegant way to express this=
?
> I'm after something that is logically equivalent, but easier to write and
> clearer to read.
>
> Garth
>

A general way to perform a multi-key sort is:
# assuming sort() is a stable sort algorithm, e.g. merge sort
  foo.sort! {|a,b|
     # starting from the least important key
     a.magic(b)
  }
  foo.sort! {|a,b|
     # sort again using the second-least important key
     b.key1 <=3D> a.key1
  }
  # repeat until you are done with the most important key

I guess you can generalize this using an array of Lambdas.

One potential disadvantage of this for your particular case is that,
a.magic(b) is always performed even if a.key0 !=3D b.key0. As you have
stated, this is quite expensive, and can make the above general scheme
much more expensive than your way.