http://www.perlmonks.org?node_id=693183


in reply to Predefined Sort

I'm having a bit of trouble understanding what you want your sort criteria to be?

Near as I can tell you either want to sort in some type of reverse numeric order perhaps ignoring certain values OR you want to sort all ports in a list based on an order that you predefine.

For sorting a list based on predefined order where your predefined order is stored in an array @predefined:
foreach $element (@dports) { $count_hash{$element}++; } foreach $key (@predefined) { print "$key\n" x $count_hash{$key} if $count_hash{$key}; }
For sorting in numeric reverse order:
my @sorted = sort {$b <=> $a} @dports;

If you are filtering out certain groups we'd have to stack this command with some type of grep.

Hope this helps,
Kris

Replies are listed 'Best First'.
Re^2: Predefined Sort
by kyle (Abbot) on Jun 20, 2008 at 16:40 UTC

    For sorting in reverse order, this is easier to understand and executes just as quickly:

    my @sorted = reverse sort {$a <=> $b} @dports

    When you swap $a and $b, there's a much better chance that someone reading through later won't notice that (particularly if the expression gets bigger and more complicated). Sticking reverse in is obvious.

      Just as quickly? Looks like (surprisingly, to me at least) ~9-10% faster on average.

      use Benchmark qw( timethese cmpthese ); use List::Util qw( shuffle ); for my $max (qw( 100 200 500 1000 2000 5000 )) { print "results for $max elems\n"; my @big_list = shuffle 1 .. $max; cmpthese( -1, { plain_sort => sub { my @local = sort { $b <=> $a } @big_list; }, reversed => sub { my @local = reverse sort { $a <=> $b } @big_list; }, } ); print "\n"; } exit 0; __END__ results for 100 elems               Rate plain_sort   reversed plain_sort 46849/s         --        -8% reversed   50717/s         8%         -- results for 200 elems               Rate plain_sort   reversed plain_sort 20676/s         --       -12% reversed   23424/s        13%         -- results for 500 elems              Rate plain_sort   reversed plain_sort 7657/s         --        -9% reversed   8374/s         9%         -- results for 1000 elems              Rate plain_sort   reversed plain_sort 3490/s         --        -8% reversed   3794/s         9%         -- results for 2000 elems              Rate plain_sort   reversed plain_sort 1599/s         --        -9% reversed   1756/s        10%         -- results for 5000 elems             Rate plain_sort   reversed plain_sort 553/s         --       -10% reversed   613/s        11%         --

      This space reserved for the update when someone points out my obvious benchmark fau pas . . . :)

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

        I usually think of the margin of error for Benchmark as about 10%. Any difference smaller than that is likely to be noise. This might also be a case where you move the code from place to place in the file and it changes speed (see No More Meaningless Benchmarks!).

        Or maybe it's faster to say {$a<=>$b} rather than {$b<=>$a} for some reason. If I run your benchmark, changing only reverse sort to sort (so the 'reversed' case actually sorts forward), the results look about the same—{$a<=>$b} wins.

        In any case, I'll probably keep thinking of them as "the same speed", benchmarks be damned.

      Good point. I like reverse sort {$a <=> $b} @unsorted for readability/maintenance.
      I think I'd probably use it, but is it really true that it executes just as quickly?
      Doesn't reverse have to re-evaluate the list given to it before executing?
      This would mean are evaluating the contents of the unsorted list twice: once to perform an ascending sort and again to perform a reverse.

      I do a lot of large batch database processing, and I'm fond of anything which is more efficient. If I had to execute the sort a few million times in a loop or give it an extremely large list such as all rows in my database, I could see the single sort approach being more efficient. Please let me know if I'm missing some, but in the meantime I'm off to use Benchmark to try this out.