in reply to Re^4: top ten things every Perl hacker should know
in thread top ten things every Perl hacker should know

Let's take a list of files and use a Schwartzian Transform to sort it by file size descending, then alphabetical order ascending.
my @sorted_files = map {$_->[0]} sort {$b->[1] <=> $a->[1] or $a->[0] cmp $b->[0]} map {[$_, -s]} @files;
Here is the same code written as a normal sort.
my @sorted_files = sort {-s $b <=> -s $a or $a cmp $b} @files;
Clearly the Schwartzian Transform is more complex. But if you have a list of 1000 files, it's also about 10 times faster. Which is why we learn it.

Now to explain my Ruby comment. In Ruby, arrays have a sort_by method. So in this example you'd write:

sorted_files = files.sort_by {|f| [- test(?s, f), f]};
and you've written the more efficient sort with less code than the regular sort. This does not work in Perl first of all because we don't have a sort_by method, and furthermore because Perl doesn't do anything useful when you try to sort array references. (Ruby sorts them lexicographically, with each field sorting in its "natural" way.)

Replies are listed 'Best First'.
Re^6: top ten things every Perl hacker should know
by qq (Hermit) on Mar 18, 2006 at 20:21 UTC

    We sort of have a sort_by method in Sort::Maker. But I've never liked the api. There is no denying that an ST is a scary sight to a new programmer not familiar with the idiom. I'd argue it should be wrapped in a sub for clarity most often.

    I like the PBP argument for using List::Util and List::MoreUtils functions such as any rather than idiomatic uses of grep. It makes your intention clear, and prevents you from thinking in syntax - no matter how comfortable and familiar that syntax is.

    update: added some words for clarity

      We sort of have a sort_by method in Sort::Maker. But I've never liked the api

      you should try Sort::Key, it has a very simple API and it's faster and uses less memory than any other perl sorting technique:

      use Sort::Key qw(keysort); my @sorted = keysort { genkey($_) } @data;