Tuesday, September 29, 2009

Daten Scheibchenweise...

Hier mal wieder ein Artikel aus einer früheren Ausgabe des Perl-Magazins "$foo":

Daten Scheibchenweise...

Ein nützliches Feature von Perl ist es, sogenannte "Slices" verwenden zu können. Wörtlich übersetzt heißt es "Scheiben". Diese "Scheiben" sind bei Listen/Arrays häufig gewünscht.

Slices im Alltag

Folgende Situation: Eine Person A war beim Arzt und benötigt Medikamente. A geht zur Apotheke X, um diese Sachen zu besorgen. X ist wie ein großes Array (1. Element: Nasenspray, 2. Element: Aspirin,...). A möchte natürlich nicht die ganze Apotheke (nicht das ganze Array) haben, sondern nur einzelne Sachen daraus. A hat jetzt zwei Möglichkeiten:

1. A sagt dem Apotheker ein Medikament, lässt den Apotheker das Medikament holen, nennt danach das nächste Element und so weiter bis A alle Sachen bekommen hat.

2. A gibt dem Apotheker eine Liste mit den Arzneinamen und lässt den Apotheker alle Medikamente holen. Der Apotheker kommt mit einem ganzen Korb voll mit den Arzneipäckchen.

Slices in Perl

So etwas kann ganz einfach in Perl nachgebildet werden, wie die Listings x-y zeigen.

# die Apotheke
my @apotheke = ('Nasenspray', 'Aspirin', 'Hustensaft', 'Allergietabletten');

# A benötigt folgende Medikamente
# hier sind aber die Arzneinamen schon
# durch den Index in der Apotheke ersetzt
my @rezept = (0,2);

# A gibt dem Apotheker und bekommt den Korb voll mit Medikamenten
my @korb = @apotheke[ @rezept ];

print $_,"\n" for @korb;

Beim Heraussuchen der Slices ( @apotheke[ @rezept ]; ) muss das "@" vor apotheke stehen, weil diese Operation eine Liste zurückliefert (im Gegensatz zu dem Zugriff auf einzelne Elemente - $apotheke[$index]).

Wichtig ist auch, dass die Elemente in der gleichen Reihenfolge zurückgeliefert werden, wie die Indexliste ist, in diesem Fall also "Nasenspray" und dann "Hustensaft". Wäre das Rezept anders herum ( my @rezept = (2,0) ), wäre zuerst der Hustensaft im Korb und dann das Nasenspray.

Hashslices

Analog zu den Arrayslices oben gibt es in Perl auch noch die Hashslices, die aber im Prinzip genauso funktionieren. Hier eine etwas andere Situation:

Ein Rechtsanwalt kommt in das Gerichtsarchiv und möchte die Unterlagen zu mehreren Fällen einsehen. Dazu hat er sich in seiner Kanzlei schon eine Liste mit Aktenzeichen angefertigt. Auch hier hat der Anwalt wieder die zwei Möglichkeiten, den Archivar einzeln losschicken oder dem Archivar einfach die Liste geben und der Archivar kommt mit einer ganzen Ladung an Aktenordnern zurück. Die erste Möglichkeit würden den Archivar wahrscheinlich ärgern, die zweite Möglichkeit ist aber optimal.

Das ganze in Perl:

my %archiv = (
az0815 => 'Akte zum Aktenzeichen 0815',
az2373 => 'Akte zum Aktenzeichen 2373',
az2371 => 'Akte zum Aktenzeichen 2371',
);

my @liste = qw(az0815 az2371);

my @akten = @archive{ @liste }

Slices als lvalue

Die Slices kann man nicht nur für das Auslesen von Daten verwenden, sondern auch für Zuweisungen. Soll zum Beispiel ein Hash verwendet werden, der später für eine reine Existenzüberprüfung dient, kann man das so machen:

my @keys = qw(key1 key2 key3);
my %hash;

@hash{ @keys } = (1) x scalar @keys;

Jetzt wird für jeden Schlüssel ein Eintrag im Hash erstellt. Jeder Schlüssel soll den Wert "1" erhalten. Deswegen muss eine Liste mit "1"en zugewiesen werden.

Ein häufiger Fehler, der gemacht wird, ist folgender:

@hash{ @keys } = 1;

Hier wird aber nicht für jeden Schlüssel ein "1" gespeichert, sondern nur für den ersten Schlüssel. Die restlichen Schlüssel erhalten den Wert "undef". Mit dem "(1) x scalar @keys" wird eine Liste erzeugt, die genauso lang ist wie die Liste der Schlüssel.

Analog funktioniert es für Arrayslices.

my @array = (1..10);
@array[2,4,6] = (99,98,97);

Hier werden in dem Array die Elemente mit den Indizes 2,4,6 durch die Zahlen in der zugewiesenen Liste ersetzt. $array[2] ist dann 99, $array[4] ist dann 98 und so weiter.

No comments: