[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