[Munich-pm] sort mit curried function
Stephen Riehm
japh at opensauce.de
Mo Nov 19 13:26:52 PST 2012
Hi Jungs,
mag hier niemand das "Schwarzian Transform"?
#!/usr/bin/perl
use strict;
use warnings;
my @liste = ( { x => 1, y => 4 }, { x => 3, y => 2 } );
my $key = 'y';
my @sortierte_liste = map { $_->[0] } # nur noch das
original ref weiter geben
sort { $a->[1] <=> $b->[1] } # billige Vergleich
map { [ $_, $_->{$key} ] } # berechne den
teueren Sort-Schlüssel
@liste;
foreach my $h ( @sortierte_liste ) {
printf "%d %d\n", $h->{x}, $h->{y};
}
(das geht natürlich auch ohne zwischen-Liste)
Vorteile:
beliebig komplexe Sortierungen werden nicht beliebig komplex (die
Struktur bleibt immer gleich)
wenn teuerer Vergleichswerte im Spiel sind - werden sie nur einmal
pro Eintrag in der Liste berechnet (ie: wichtig wenn man Objekte
sortieren will)
Nur meine 3,56€ (2c + Inflation :-()
Steve
On 19.11.2012, at 12:40, Harald Joerg wrote:
> Hallo Robert,
>
> Dass Deine Überlegungen nicht funktionieren, liegt daran, dass
> sort SUBNAME LIST syntaktisch etwas "eingeschränkt" ist.
>
> Es geht aber, mit einfacherem bykey, wie folgt:
>
> ----------------------------------------------------------------------
> #!/usr/bin/perl -w
>
> use strict;
>
> my @liste = ({ x => 1, y => 4}, {x => 3, y => 2});
>
> foreach my $h (sort {bykey('x')} @liste){
> print $h->{x}, $h->{y}, "\n";
> }
>
> sub bykey {
> my $key = shift;
>
> return($a->{$key} <=> $b->{$key});
> }
> ----------------------------------------------------------------------
>
> * Anstelle von sort SUBNAME LIST verwende ich sort BLOCK LIST,
> das frisst der Parser leichter.
>
> * In bykey sind $a und $b direkt verfügbar, das sind package globals
> (@Marek: Die muss man also nicht übergeben). Der Code ist nicht
> reentrant, es wäre also unklug, innerhalb von bykey nochmal einen
> sort-Aufruf zu haben (ginge auch, aber nur über sort mit
> Prototypes).
>
> Es ist aber nicht nötig, eine eigene Subroutine zu erzeugen.
> (@Roderich: Geht nicht - gibt's nicht :))
> --
> Cheers,
> haj
>
>
>
> "Robert C. Helling" <helling at lmu.de> writes:
>
>> Hallo,
>>
>> ich stehe grade mal wieder auf dem Schlauch. Ich habe eine Liste mit
>> Hashreferenzen, wobei die Hashes mehrere Felder vom gleichen Typ
>> haben.
>> Nun moechte ich gerne die Liste sortieren anhand jeweils eines
>> Feldes des
>> Hashes. Die Vergleichsfunktion ist etwas kompliziert. Daher will
>> ich sie
>> nicht fuer jedes Hashfeld neu schreiben, sondern mach lieber eine
>> gemeinsame Vergleichsfunktion, die den Namen des Feldes bekommt und
>> dann
>> entsprechend gecurried wird. Schematisch wie in diesem Beispiel:
>>
>> #!/usr/bin/perl -w
>>
>> use strict;
>>
>> my @liste = ({ x => 1, y => 4}, {x => 3, y => 2});
>>
>>
>> my $byx = &bykey('x');
>>
>> foreach my $h (sort $byx @liste){
>> print $h->{x}, $h->{y}, "\n";
>> }
>>
>> sub bykey {
>> my $key = shift;
>>
>> return(sub {$a->{$key} <=> $b->{$key}});
>> }
>>
>>
>> Das funktioniert so. Meine Frage ist nun: Wie komme ich ohne die
>> Dummyvariable $byx aus? Ich habe zB schon probiert
>>
>> foreach my $h (sort &&bykey('x') @liste){
>>
>> aber das gibt einen Syntaxerror. Auch aehnliche Versionen mit
>> weniger &'s
>> und mehr oder wenigen Klammern verschiedenen Typs habe ich
>> probiert, aber
>> nichts davon funktionierte.
>>
>> Wer erleuchtet mich?
>>
>> Viele Gruesse
>> Robert
> _______________________________________________
> Munich-pm mailing list http://munich.pm.org/
> Munich-pm at pm.org
> http://mail.pm.org/mailman/listinfo/munich-pm
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.pm.org/pipermail/munich-pm/attachments/20121119/b30a1b74/attachment.html>
Mehr Informationen über die Mailingliste Munich-pm