Suche…


Einführung

Für das Sortieren von Listen von Dingen hat Perl nur eine einzige Funktion, die überraschenderweise als sort . Es ist flexibel genug, um alle Arten von Elementen zu sortieren: Zahlen, Zeichenfolgen in beliebiger Anzahl von Kodierungen, verschachtelte Datenstrukturen oder Objekte. Aufgrund seiner Flexibilität gibt es jedoch einige Tricks und Idiome, die man für seine Anwendung lernen kann.

Syntax

  • SUBNAME LIST sortieren
  • BLOCKLISTE sortieren
  • Sortierliste

Grundlegende lexikalische Sortierung

@sorted = sort @list;

@sorted = sort { $a cmp $b } @list;

sub compare { $a cmp $b }
@sorted = sort compare @list;

Die drei obigen Beispiele machen genau dasselbe. Wenn Sie keine Komparatorfunktion oder keinen Komparator angeben, geht die sort davon aus, dass Sie die Liste rechts von ihrer Liste lexikalisch sort möchten. Dies ist in der Regel die Form, die Sie möchten, wenn Sie Ihre Daten nur in einer vorhersagbaren Reihenfolge benötigen und sich nicht um sprachliche Korrektheit kümmern.

sort übergibt @list in @list an die Vergleicherfunktion, die sort @list , welches Element größer ist. Der cmp Operator führt dies für Zeichenfolgen aus, während <=> das gleiche für Zahlen tut. Der Komparator wird ziemlich oft aufgerufen, im Durchschnitt n * log ( n ) mal, wobei n die Anzahl der zu sortierenden Elemente ist. Daher ist es wichtig, dass er schnell ist. Deshalb verwendet sort vordefinierte globale Paketvariablen ( $a und $b ), um die zu vergleichenden Elemente mit dem Block oder der Funktion zu übergeben, anstatt die richtigen Funktionsparameter zu verwenden.

Wenn Sie use locale , cmp die locale-spezifische Sortierreihenfolge, z. B. sortiert Å nach A unter einem dänischen Locale, nach Z unter einem englischen oder deutschen. Es berücksichtigt jedoch nicht die komplexeren Unicode-Sortierregeln und bietet auch keine Kontrolle über die Reihenfolge. Beispielsweise werden Telefonbücher oft anders als Wörterbücher sortiert. In diesen Fällen werden die Module Unicode::Collate und insbesondere Unicode::Collate::Locale empfohlen.

Numerische Sortierung

@sorted = sort { $a <=> $b } @list;

Beim Vergleich von $a und $b mit dem Operator <=> wird sichergestellt, dass sie standardmäßig numerisch und nicht textlich verglichen werden.

Sortierung umkehren

@sorted = sort { $b <=> $a } @list;
@sorted = reverse sort { $a <=> $b } @list;

Das Sortieren der Elemente in absteigender Reihenfolge kann einfach durch Vertauschen von $a und $b im Vergleicherblock erreicht werden. Manche Menschen bevorzugen jedoch die Klarheit einer separaten reverse auch wenn sie etwas langsamer ist.

Die schwartzianische Transformation

Dies ist wahrscheinlich das bekannteste Beispiel für eine Sortieroptimierung, bei der die funktionalen Programmierfunktionen von Perl zum Einsatz kommen, wenn die Sortierreihenfolge der Artikel von einer teuren Funktion abhängt.

# What you would usually do
@sorted = sort { slow($a) <=> slow($b) } @list;

# What you do to make it faster
@sorted =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [ $_, slow($_) ] }
@list;

Das Problem beim ersten Beispiel ist, dass der Komparator sehr oft aufgerufen wird und die Werte immer wieder mit einer langsamen Funktion neu berechnet. Ein typisches Beispiel wäre das Sortieren der Dateinamen nach ihrer Dateigröße:

use File::stat;
@sorted = sort { stat($a)->size <=> stat($b)->size } glob "*";

Dies funktioniert, aber im besten Fall sind zwei Systemaufrufe pro Vergleich erforderlich. Im schlimmsten Fall muss der Datenträger zweimal für jeden einzelnen Vergleich aufgerufen werden, und dieser Datenträger befindet sich möglicherweise in einem überlasteten Dateiserver auf der anderen Seite des Planet.

Tritt in Randall Schwartz 'Trick ein.

Die Schwartzian-Transformation durchläuft @list list @list durch drei Funktionen von unten nach oben. Die erste map wandelt jeden Eintrag in eine Liste mit zwei Elementen des ursprünglichen Elements und das Ergebnis der langsamen Funktion als Sortierschlüssel um. Am Ende haben wir slow() genau einmal für jedes Element aufgerufen. Die folgende sort kann dann einfach auf den Sortierschlüssel zugreifen, indem Sie in der Liste nachschauen. Als wir über die Sortierschlüssel nicht kümmern , sondern brauchen nur die ursprünglichen Elemente in sortierter Reihenfolge, die letzte map wirft die Zweielementlisten aus der bereits sortierten Liste aus erhält weg @sort und gibt eine Liste von nur ihren ersten Mitgliedern .

Groß- und Kleinschreibung

Die traditionelle Methode, um die sort ignorieren zu lassen, besteht uc zum Vergleich Strings an lc oder uc zu übergeben:

@sorted = sort { lc($a) cmp lc($b) } @list;

Dies funktioniert auf allen Versionen von Perl 5 und ist für Englisch völlig ausreichend. Es spielt keine Rolle, ob Sie uc oder lc . Es ist jedoch ein Problem für Sprachen wie Griechisch oder Türkisch, wo es keine 1: 1-Entsprechung zwischen Groß- und Kleinbuchstaben gibt. Je nach Verwendung von uc oder lc Sie unterschiedliche Ergebnisse. Daher haben Perl 5.16 und höher eine Case-Folding- Funktion namens fc , mit der dieses Problem vermieden wird. Moderne mehrsprachige Sortierungen sollten daher Folgendes verwenden:

@sorted = sort { fc($a) cmp fc($b) } @list;


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow