Schwartzian transform

Aaron Crane perl at aaroncrane.co.uk
Wed Aug 13 12:17:48 BST 2014


Dermot <paikkos at gmail.com> wrote:
> my $count = 1;
> my @sorted =
>     map { $ref->{ $_->[0] }->{position} = $count++; $ref->{ $_->[0] } }
>     sort { $a->[1] <=> $b->[1] }
>     map [ $_, $ref->{$_}->{position} ],
>     keys %{ $ref };

It's not clear to me that the Schwartzian Transform adds anything to
this code: with it, you have to create an array ref for every input
hash ref, and then sort by an element of each array ref, but without
it, you could simply sort by an element of each input hash ref:

my @sorted = sort { $a->{position} <=> $b->{position} } values %$ref;

I haven't measured the relative execution speed of this code and the
version using the Schwartzian Transform; I think the enormous increase
in clarity you get this way will outweigh any speed improvement you
might get from the ST. (If indeed there is any — since the key you're
sorting on is quick to calculate, it's not impossible that the extra
allocations needed for the ST will make it actually slower in
practice.)

If you don't actually need to keep @sorted around, the whole thing can
be even simpler:

my $position = 1;
$_->{position} = $position++
    for sort { $a->{position} <=> $b->{position} } values %$ref;

I've also renamed your $count variable to $position, because I think
that more accurately reflects what it contains.

-- 
Aaron Crane ** http://aaroncrane.co.uk/



More information about the london.pm mailing list