Beispiel einer 2x3-Matrix
(
A= (
a b c d e f )
Um eine einzelne Variable zu beschreiben, setzt man Zeile und Spalte als Index an den Namen der Matrix, z.B.:
Will man nun ein Perl-Programm schreiben, das mit Matrizen arbeiten soll, muß man sich überlegen, wie man sie geeignet speichert. Da Arrays ein geordnetes eindimensionales (
A = b 1,2
#!/usr/local/bin/perl -w @zeile_1 = ( 'a', 'b', 'c' ); @zeile_2 = ( 'd', 'e', 'f' ); @matrix = ( @zeile_1, @zeile_2 ); # 6-elementiges Array ! |
Obiger Code erzeugt keineswegs eine zweidimensionale Matrix in
@matrix
. In der letzten Zeile werden nämlich
zuerst die beiden Zeilen-Arrays @zeile_1
und
@zeile_2
als Listen dargestellt, die
dann vor der Zuweisung zu einer 6-elementigen Liste vereinigt
werden. Die letzte Zeile des obigen Programms ist also äquivalent zu:
@matrix = ( 'a', 'b', 'c', 'd', 'e', 'f' ); |
Die Ursache für dieses Verhalten liegt darin begründet, daß Arrays in Perl grundsätzlich nur skalare Größen enthalten, aber keine Arrays oder Hashe (sie werden, wie oben beschrieben, vorher umgewandelt).
#!/usr/local/bin/perl -w @zeile_1 = ( 'a', 'b', 'c' ); @zeile_2 = ( 'd', 'e', 'f' ); @matrix = ( \@zeile_1, \@zeile_2 ); |
Nun enthält das Array @matrix
zwei (skalare) Elemente,
die ihrerseits jeweils eine Referenz auf ein Zeilen-Array sind.
Wie kann man nun auf die einzelnen Matrixelemente zugreifen ?
Die Elemente $matrix[0]
und $matrix[1]
enthalten jeweils eine Referenz auf ein Array, so daß nach
der Dereferenzierung die Zeilen-Arrays zur Verfügung stehen.
An dieser Stelle sei noch einmal darauf hingewiesen, daß in Perl
Array-Indizes üblicherweise bei 0 anfangen. Man sollte nicht die
Variable $[
auf 1 setzen,
um bei 1 mit der Zählung zu
beginnen, sondern besser die Elemente oder Zeilen-Arrays gezielt an die
Positionen 1,2,... der jeweiligen Arrays schreiben. Der Einfachheit
halber wird in den Beispielen auf dieser Seite darauf verzichtet,
so daß zu beachten ist, daß von den Matrix-Indizes
immer jeweils 1 zu subtrahieren ist, um die Array-Indizes zu erhalten.
Ein ausführliches Beispiel sieht dann so aus:
#!/usr/local/bin/perl -w @zeile_1 = ( 'a', 'b', 'c' ); @zeile_2 = ( 'd', 'e', 'f' ); @matrix = ( \@zeile_1, \@zeile_2 ); $ref_1 = $matrix[0]; @zeile_1 = @$ref_1; $ref_2 = $matrix[1]; @zeile_2 = @$ref_2; print "1) @zeile_1\n"; print "2) @zeile_2\n"; |
1) a b c 2) d e f |
Der Zugriff läßt sich natürlich auch kompakter programmieren:
@matrix = ( \@zeile_1, \@zeile_2 ); print "1) @{$matrix[0]}\n"; print "2) @{$matrix[1]}\n"; |
Wegen der Präzedenzregeln müssen bei den Dereferenzierungen
hier geschweifte Klammern gesetzt werden (ansonsten würde Perl
zuerst versuchen, $matrix
zu dereferenzieren und erst
dann dort das Element mit dem entsprechenden Index suchen).
Mit Hilfe dieses Mechanismus lassen sich auch gezielt einzelne Matrixelemente auslesen und mit Werten besetzen:
#!/usr/local/bin/perl -w @zeile_1 = ( 'a', 'b', 'c' ); @zeile_2 = ( 'd', 'e', 'f' ); @matrix = ( \@zeile_1, \@zeile_2 ); print "Matrix(1,2) = ${$matrix[0]}[1]\n"; ${$matrix[1]}[2] = 'x'; print "1) @{$matrix[0]}\n"; print "2) @{$matrix[1]}\n"; |
Matrix(1,2) = b 1) a b c 2) d e x |
Eine alternative Schreibweise für den Zugriff auf ein
einzelnes Element bietet der Pfeil-Operator
"->
" (nicht zu verwechseln mit "=>
"
als Kommaersatz):
print "Matrix(1,2) = $matrix[0]->[1]\n"; $matrix[1]->[2] = 'x'; |
Und auch dies läßt sich noch verkürzen, da Perl zwischen zwei aufeinander folgenden Klammern (eckig oder geschweift) automatisch einen Pfeil-Operator setzt. Dadurch läßt sich eine sehr intuitive und übersichtliche Schreibweise erreichen:
print "Matrix(1,2) = $matrix[0][1]\n"; $matrix[1][2] = 'x'; |
Beispiel:
#!/usr/local/bin/perl -w @array = ( 10, 20, 30, 40 ); # normales Array $ref_array = [ 10, 20, 30, 40 ]; # anonymes Array |
Da ein solches anonymes Array eine Referenz liefert, kann man daraus direkt mehrdimensionale Felder erstellen. Die weiter oben als Beispiel verwendete Matrix ließe sich dann auch so erzeugen:
#!/usr/local/bin/perl -w @matrix = ( [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] ); |
Noch einmal zur Erinnerung: würde man hier runde statt eckige
Klammern verwenden, erhielte man ein einfaches 6-elementiges Array
in @matrix
.
Auf die Matrixeinträge kann hier genauso zugegriffen werden wie weiter oben bei den benannten Arrays beschrieben.
Ein Beispiel, wie man die gesamte Matrix ausgeben kann:
#!/usr/local/bin/perl -w @matrix = ( [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] ); foreach $ref_zeile (@matrix) { foreach $spalte (@$ref_zeile) { print "$spalte " } print "\n"; } |
a b c d e f |
Da eine solche zweidimensionale Datenstruktur letztlich auf
(eindimensionalen) Arrays beruht, kann man sie mit Hilfe bekannter
Funktionen wie push()
oder pop()
dynamisch verändern. So läßt sich die oben
definierte Matrix beliebig bearbeiten:
#!/usr/local/bin/perl -w @matrix = ( [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] ); pop( @{$matrix[1]} ); # 'f' entfernen unshift( @{$matrix[0]}, 'M' ); # 'M' einfügen push(@matrix, [ sort( 'i', 'h', 'g' ) ] ); # 3.Zeile foreach $ref_zeile (@matrix) { foreach $spalte (@$ref_zeile) { print "$spalte " } print "\n"; } |
M a b c d e g h i |
Wie man sieht, wird auch der (Array-)Rückgabewert einer Funktion (hier:
sort()
) durch [...]
in ein anonymes Array
umgewandelt.
Autor: Eike Grote | Letzte Änderung: 06.09.1998 |