in reply to Stable sorting in Perl

This might be an answer to your question. From perldoc sort:

NAME
       sort - perl pragma to control sort() behaviour

SYNOPSIS
           use sort 'stable';          # guarantee stability
           use sort '_quicksort';      # use a quicksort algorithm
           use sort '_mergesort';      # use a mergesort algorithm
           use sort 'defaults';        # revert to default behavior
           no  sort 'stable';          # stability not important

           use sort '_qsort';          # alias for quicksort

           my $current = sort::current();      # identify prevailing algorithm

Liz

Replies are listed 'Best First'.
Re^2: Stable sorting in Perl (old)
by tye (Sage) on Aug 27, 2003 at 19:24 UTC

    In case you aren't on the leading edge of Perl versions and don't have sort.pm, you can get a stable sort fairly easily:

    # Replace: my @sorted= sort @list; # with: my @index= sort { $list[$a] cmp $list[$b] || $a <=> $b } 0..$#list; my @sorted= @list[@index]; # or with (to avoid @index remaining in scope): my @sorted= @list[ sort { $list[$a] cmp $list[$b] || $a <=> $b } 0..$#list ];
    For a more complex form of sort:
    # Replace: my @sorted= map { RESTORE($_) } sort { COMPARE($a,$b) } map { XFORM($_) } @list; # with: my @sortOn= map { XFORM($_) } @list; my @index= sort { COMPARE($sortOn[$a],sortOn[$b]) || $a <=> $b } 0..$#sortOn; my @sorted= @list[@index]; # or with (to avoid temporaries remaining in scope): my @sorted= do { my @sortOn= map { XFORM($_) } @list; @list[ sort { COMPARE($sortOn[$a],sortOn[$b]) || $a <=> $b } 0..$#sortOn; ]; };
    Note that this allows us to avoid the RESTORE() step which often means that the XFORM() step becomes much simpler.

    If you are going for speed by avoiding COMPARE() [the advantage of which has been reduced (but not eliminated) for some cases due to new optimizations], then consider:

    # Replace: my @sorted= map { RESTORE($_) } sort map { XFORM($_) } @list; # with:
    my @sorted= @list[ map { unpack "N", substr($_,-4) } sort map { XFORM($list[$_]) . pack "N", $_ } 0..$#list ];
    Which may become my favorite sorting technique because it gives you almost maximum speed while not requiring RESTORE() (which is often the hardest part).

    I like it so much, I've made it an official snippet: fast, flexible, stable sort.

    (updated.)

                    - tye
      Sorry, maybe I just don't get it, but why is your first example a stable sort?
      my @unsorted = ([1,1], [2,1], [1,2], [2,2], [2,3], [1,3], [2,4], [1,4]); print join( ' ', map { $_->[0].$_->[1] } sort { $a->[0] <=> $b->[0] } @unsorted) . "\n"; my @sortedindices = sort { $unsorted[$a]->[0] <=> $unsorted[$b]->[0] } 0..$#unsorted; print join ( ' ', map { $_->[0].$_->[1] } @unsorted[@sortedindices]); __END__ 11 12 13 14 23 21 24 22 11 12 13 14 23 21 24 22
      Both sorts are not stable.

      daniel.

      update: got it now ;-) replace compare-function by
      $unsorted[$a]->[0] <=> $unsorted[$b]->[0] || $a <=> $b
      This is perfect ... I'm going to pin this to the wall of my cube! ++

        tyes node is one of the better collections of the various advanced sorting techniques that I've seen. However you may want to have also have a look at one of PM's earliest nodes, and the canonical Schwartzian Transform (ST), which is the term generally given to most of these techniques in books. There is also the Guttman Rosler Transform (GRT) which is IMO a specialisation of the ST, and of which class I would say that tyes variant belongs to, although I suspect that perhaps it deserves its own name, possibly the Tye Transform? :-)


        ---
        demerphq

        <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
Re: Re: Stable sorting in Perl
by sweetblood (Prior) on Aug 27, 2003 at 19:41 UTC
    I saw a reference to that pragma somewhere on the internet however I don't get that when I do "perldoc -f sort". If I try use sort 'stable'; (et-al) I get: "Can't locate sort.pm ..." etc.
    Do I have to have a seperate sort.pm from cpan? Or (and maybe this is most likely) is this not available in perl v5.6.0?
    But thanks for the reply. ++
      There is a subtle difference between:
      perldoc sort
      
      and
      perldoc -f sort
      
      The former gives you the documentation of the sort pragma, whereas the latter gives you the documentation of the sort function. But indeed, you appear to need at least 5.8.0 for the sort pragma.

      Liz

        Ahhh... When I do perldoc sort I get "No documentation for sort..." So only perldoc -f sort gives me anything. I think you're right, I must need 5.8.0 or better for the sort pragma. Thanks!