anaboe.net

Sortieren eines Arrays nach mehreren Kriterien (Schwartzsche Transformation)

Zielstellung

Sie haben ein Array aus Strings vorliegen, die ihrerseits Datenreihen repräsentieren. Innerhalb der einzelnen Strings sind die Felder durch einen Separator getrennt (z.B. ein Semikolon). Dieses Array möchten Sie nach mehreren Feldern sortieren.

Perl - Code

use strict;
use diagnostics;

# ein unsortiertes Array von Personen
# Format: 'Nachname,Vorname,Alter'
my @unsorted = ('Müller,Karl,82',
                'Müller,Karla,79',
                'Schulze,Maria,29',
                'Schulze,Karl,32',
                'Mayer,Dorothea,77',
                'Mayer,Karl,78',
                'Wichtig,Karl,66,',
                'Wichtig,Karla,64'
               );
               
# Sortiert werden soll zunächst nach
# dem Vornamen, dann nach dem Alter
my @sorted = map  { $_->[0] }
             sort { $a->[1] cmp $b->[1] || $a->[2] <=> $b-> [2] }
             map  { [ $_, (split /,/)[1,2] ] } @unsorted;

# Ausgabe des Ergebnisses
print join "\n", @sorted;

Erläuterungen

Wir bedienen uns der sog. Schwartzschen Transformation, wie sie in perlfaq4 beschrieben ist.

Um den Sortieralgorithmus zu verstehen, muss man die Anweisung von hinten nach vorn lesen:

Das letzte map erstellt aus @unsorted eine temporäre Liste aus anonymen Arrays. In diesen anonymen Arrays werden das Originalelement ($_) sowie die Felder, nach denen sortiert werden soll, abgelegt. Zu diesem Zweck wird jede Zeile des Ursprungsarrays mittels split an den Kommas zerlegt. Wichtig ist hier zu wissen, dass (split /,/) ein Array liefert, von dem aber nur das 2. Element (Vorname) und das dritte Element (Alter) benötigt werden.

Diese temporäre Liste wird dann mittels sort sortiert. Da nach zwei Kriterien sortiert werden soll, sind diese zwei Vergleiche wie gezeigt innerhalb von sort mittels einer ODER-Verknüpfung || zu notieren. Der Vergleichsoperator ist typenabhängig zu wählen, so wie in der Dokumentation zu sort beschrieben.

In der obersten map-Anweisung wird alles wieder sortiert zusammengefügt.