mehrdimensionales Array abfragen
brain
- perl
Hallo,
ich erzeuge so ein Array:
push (@stoerliste,[$stoernr,$stoertyp,$stoertext,$stoersms,$stoerreserve1,$stoerreserve2,$stoerreserve3]);
Und möchte über eine "foreach" Schleife darauf zugreifen.
my ($nr) = @_;
my $zaehler = 0;
foreach(@stoerliste)
{
if (@$_[0] == $nr)
{
return $zaehler;
}
$zaehler++;
}
Hier kommt aber bei "@$_[0]" die Fehlermeldung, warum ????
Es sollte doch so funktionieren.
Gruß
brain
Hi,
schau mal hier:
# Anonyme Arrays
###########################################################################
use strict;
# Es soll ein Array erstellt werden in welchem
# verschiedene Werte abgelegt sind, dies wird ein anonymes Array:
my @names;
push @names, ['Rolle', 'Rops', 'Karlsruhe'];
push @names, ['Erwin', 'Blubbermann', 'Unterlandhausen'];
push @names, ['Fips', 'Fuzziheinrich', 'Kunkelfriedbach'];
# Die Werte einzeln wieder ausgeben:
print $names[0]->[0], "\n"; # Rolle
print $names[0]->[1], "\n"; # Rops
print $names[0]->[2], "\n"; # Karlsruhe
print $names[1]->[0], "\n"; # Erwin
print "\n------------------------------\n";
# Oder alles in einer Schleife ausgeben:
# Vorher den Nachnamen von Fips ändern
$names[2]->[1] = 'Fuzziblubber';
foreach my $name(@names){
print "Vorname: $name->[0], Nachname: $name->[1] wohnt in $name->[2]\n";
}
# Vorname: Rolle, Nachname: Rops wohnt in Karlsruhe
# Vorname: Erwin, Nachname: Blubbermann wohnt in Unterlandhausen
# Vorname: Fips, Nachname: Fuzziblubber wohnt in Kunkelfriedbach
Hallo,
ich erzeuge so ein Array:
push (@stoerliste,[$stoernr,$stoertyp,$stoertext,$stoersms,$stoerreserve1,$stoerreserve2,$stoerreserve3]);
Du baust also einen Array,
Dessen Elemente Referenzen auf anonyme Arrays sind
Und möchte über eine "foreach" Schleife darauf zugreifen.
my ($nr) = @_;
Was zum Teufel ist @_ ?
(Ich weiss was @_ ist, aber es ist wohl schlechter Code)
my ($nr) = @_;
ist das gleiche wie
my $nr = $_[0];
my $zaehler = 0;
foreach(@stoerliste)
Merke ab hier steht dir S_ als Alias zur Verfügung.
Das blöde ist, das du im weiteren keinen Gebrauch von dem Element machst, über welches du iterierst.
{
if (@$_[0] == $nr)
Hier greifst du auf das erste Element in @_ zu, welches du in der Anname dereferenzierst, dass es eine Arrayreferenz beinhalte.
Wenn $_[0] keine Referenz ist, hast du einen Fehler
Andernfalss dereferenzierst du eine Referenz und Vergreichst sie mit einer Refernenz, was auch falsch ist.
{
return $zaehler;
Sinnlos, weil deine Abfrage immer wahr oder immer falsch ist.
}
$zaehler++;
}Hier kommt aber bei "@$_[0]" die Fehlermeldung, warum ????
Welche? Perl ist sehr freundlich zu dir
Es sollte doch so funktionieren.
Sieht nicht so aus.
Ich gewinne den Eindruck dass du nicht weisst, was $_[0] ist.
Es ist das erste Element in @_ und somit das gleiche wie $nr
Gruß
brain
vielleicht willst du das
push( @arr , [1, 2, 3] );
foreach ( @arr ){
$_->[0] == 1 and be_happy();
}
mfg Beat
Kurtz gegrüßt
Ich gewinne den Eindruck dass du nicht weisst, was $_[0] ist.
Es ist das erste Element in @_ und somit das gleiche wie $nr
Nein, $_ ist eine Array-Referenz @$_ das derefrenzierte Array und @$_[0] ist identisch zu @{$_}[0], also ein Arrayslice der Länge 1.
"Korrekter" (oder zumindest gewollt) wäre aber $$_[0] was hier "zufällig" gleich @$_[0] ist.
Wie gesagt und auch immer, beides ist schlechter Schreibstil, ein $_->[0] würde solche Missverständnisse konsequent vermeiden.
Grüße
Kurt
Nein, $_ ist eine Array-Referenz @$_ das derefrenzierte Array und @$_[0] ist identisch zu @{$_}[0], also ein Arrayslice der Länge 1.
jou
müsste ${$_}[0] heissen, oder eben $_->[0]
bei $$_[0] muss man schon die Präzedenz der Doku konsultieren.
und schreibt, falls man sich wirklich auf @_ beziehen will besser ${$_[0]}
persönlich arbeite ich lieber mit my x Aliasen in einer foreach Schleife, wenn's nicht ganz trivial ist.
mfg Beat
Kurtz gegrüßt
persönlich arbeite ich lieber mit my x Aliasen in einer foreach Schleife, wenn's nicht ganz trivial ist.
dito! :)
Grüße
Kurt
Ich gewinne den Eindruck dass du nicht weisst, was $_[0] ist.
Es ist das erste Element in @_ und somit das gleiche wie $nrNein, $_ ist eine Array-Referenz @$_ das derefrenzierte Array und @$_[0] ist identisch zu @{$_}[0], also ein Arrayslice der Länge 1.
Quatsch. @_ ist das Array der Parameter, einer Funktion und $_[0] das erste Element. $_ ist etwas völlig anderes.
Wie gesagt und auch immer, beides ist schlechter Schreibstil, ein $_->[0] würde solche Missverständnisse konsequent vermeiden.
Wäre aber in dem Falle falsch.
Struppi.
Nein, $_ ist eine Array-Referenz @$_ das derefrenzierte Array und @$_[0] ist identisch zu @{$_}[0], also ein Arrayslice der Länge 1.
Quatsch. @_ ist das Array der Parameter, einer Funktion und $_[0] das erste Element. $_ ist etwas völlig anderes.
for (["kluger","dumm"],["junge","schwaetzer"]) {
print @$_[1]
}
Nein, $_ ist eine Array-Referenz @$_ das derefrenzierte Array und @$_[0] ist identisch zu @{$_}[0], also ein Arrayslice der Länge 1.
Quatsch. @_ ist das Array der Parameter, einer Funktion und $_[0] das erste Element. $_ ist etwas völlig anderes.
for (["kluger","dumm"],["junge","schwaetzer"]) {
print @$_[1]
}
Und wo ist in deinem schönen Beispiel @\_?
Du hast hier jeweils eine Arrayreferenz in $\_ aber sehe weit breit nicht wo du auf @\_ zugreifst.
Struppi.
Du hast hier den wichtigen Satz auf den du dich beziehst und der deine Aussage zum Quatsch macht natürlich schön rausgelöscht:
Ich gewinne den Eindruck dass du nicht weisst, was $_[0] ist.
Es ist das erste Element in @_ und somit das gleiche wie $nr
Nein, $_ ist eine Array-Referenz @$_ das derefrenzierte Array und @$_[0] ist identisch zu @{$_}[0], also ein Arrayslice der Länge 1.
OK, diese Aussage an sich ist nicht falsch, aber sie hat nichts mit der davor zu tun. $_[0] ist das erste Element von @_, aber $_ ist in diesem Fall in der Schleife ein Array, aber es hat nichts mit dem Code davor zu tun, wo der Funktionsparameter übergeben wird.
Struppi.
Hier ist der Testcase
Das Paradigma ist 'use strict'
über etwas anderes brauchen wir gar nicht mehr diskutieren.
Perl Version 5.8
_____________________________________________________________________
#!C:/Programme/Perl/bin/perl.exe
use warnings;
use strict;
my @arr;
push( @arr , [21, 22, 23] , ['a', 'b', 'c'] );
foreach ( @arr ){
$_->[2]eq 23 and print STDOUT '1. $_->[2] ist ', $_->[2], "\n";
$$_[2]eq 23 and print STDOUT '2. $$_[2] ist ', $$_[2], "\n";
${$_}[2] eq 23 and print STDOUT '3. ${$_}[2] ist ', ${$_}[2], "\n";
@$_->[2] eq 23 and print STDOUT '4. @$_->[2] ist ', @$_->[2], "\n";
@$_[2] eq 23 and print STDOUT '5. @$_[2] ist ', @$_[2], "\n";
@{$_}[2] eq 23 and print STDOUT '6. @{$_}[2] ist ', @{$_}[2], "\n";
}
print STDOUT "\ndone\n";
sleep(10);
exit;
__END__
_____________________________________________________________________
Resultat:
1, 2, 3, 5, 6 produzieren ohne Warnung das gesuchte Ergebnis
4 erzeugt eine Warnung 'Using an array as reference is deprecated'
Das bedeutet:
@$_->[2] ?= @$_[2] == @{$_}[2]
Woraus man was für den Interpreter schliessen kann?
Das intern der Interpreter auf eine Abiguitat bei @$_->[2] trifft,
einen zweiten Anlauf holen muss, und die Warnung ausgibt.
Man merke dass die Fälle 4, 5 und 6 unnötig einen Array-Slice bilden,
vom dem dann doch nur das dritte Element verwendet wird.
Das ist nicht falsch aber nicht performant.
Ist dieser Test einhellig nachvollziehbar für euch?
mfg Beat
Ist dieser Test einhellig nachvollziehbar für euch?
Ja, aber der erste Teil der Aussage von Kurt, bezog sich nicht auf die Dereferenzierung der Arrayreferenz. Ich verwende in so einem Fall nur deine erste Variante dafür ist die Pfeilschreibweise gedacht, dass man leichter erkennt, dass hier eine Referenz verwendet wird.
Struppi.
Kurtz gegrüßt
@$_->[2] eq 23 and print STDOUT '4. @$_->[2] ist ', @$_->[2], "\n";
...
4 erzeugt eine Warnung 'Using an array as reference is deprecated'
Das entspricht @arr->[idx] sowas hab ich noch nie gesehen, was soll da bitte sinnvolles rauskommen???
... oh Mann...habs ausprobiert, also ehrlich, was ein Schwachsinn, das sollte ein Syntaxfehler sein kein Deprecated. Vielleicht ist das ja ein aufwärtskompatibles Relikt aus Perl4 oder älter.
Man merke dass die Fälle 4, 5 und 6 unnötig einen Array-Slice bilden,
vom dem dann doch nur das dritte Element verwendet wird.
Das ist nicht falsch aber nicht performant.
Doch in bestimmten Kontexten ist es auch Falsch, weil es sich anders verhält.
Grüße
Kurt
Kurtz gegrüßt
der Vollständigkeit halber
... oh Mann...habs ausprobiert, also ehrlich, was ein Schwachsinn, das sollte ein Syntaxfehler sein kein Deprecated. Vielleicht ist das ja ein aufwärtskompatibles Relikt aus Perl4 oder älter.
nix Perl4 nur ein alter Bug im Parser...
(D deprecated) You tried to use an array as a reference, as in
< @foo->[23] > or < @$ref->[99] >. Versions of perl <= 5.6.1 used to
allow this syntax, but shouldn't have. It is now deprecated, and will be
removed in a future version.
Mann, mann , mann ...
Gruß
Kurt
my ($nr) = @_;
Was zum Teufel ist @_ ?
(Ich weiss was @_ ist, aber es ist wohl schlechter Code)
Das ganze Mißverständniss beginnt hier.
Das ist kein schlechter Code sondern durchaus üblich, auch wenn in der Liste auf der Linken Seite nur ein Element steht, kann man das aus Gründen der Konsistenz so machen.
my($parameter_1, $parameter_2) = @_;
my ($nr) = @_;
ist das gleiche wie
my $nr = $_[0];
oder wie:
my $nr = shift;
jeder so wie er mag. shift ist zwar langsamer, das dürfte aber meistens keine Rolle spielen.
if (@$_[0] == $nr)
Hier greifst du auf das erste Element in @_ zu,
und das ist falsch!
Hier versucht er auf das erste Element in @$_ zuzugreifen.
test(qw(a b c));
sub test
{
printf "@$_[0]\n"; # Use of uninitialized value in join or string ...
$_ = [qw(a b c)];
print "@$_[0]"; # a
}
Ich gewinne den Eindruck dass du nicht weisst, was $_[0] ist.
Es ist das erste Element in @_ und somit das gleiche wie $nr
Das ist richtig (auch wenn Kurt das bestreitet).
Struppi.
jeder so wie er mag. shift ist zwar langsamer, das dürfte aber meistens keine Rolle spielen.
Ich nehme den Satz, dass @_ schlechter Code sei, gerne zurück.
Ich habe mir aber den Zugriff auf @_ abgewöhnt, weil ich die Übergabe von Referenzen in Subroutinen sinnvoller erachte.
Aus dem Grunde lehre ich es nicht gerne.
Der Geschwindigkeitsgewinn (und die Speicherersparnis) liegt eindeutig bei den Referenzen, weil der Array (oder der Hash) nicht zuerst kopiert werden muss.
Ausnahmen haben weiter ihre Berechtigung.
mfg Beat
Ich habe mir aber den Zugriff auf @_ abgewöhnt, weil ich die Übergabe von Referenzen in Subroutinen sinnvoller erachte.
Was hat das eine mit dem anderen zu tun?
Du musst so oder so auf das Array zugreifen, ob du es so wie der OP machst oder mit $_[index] oder über shift ist relativ egal und eine Sache des Geschmacks.
Struppi.
Kurtz gegrüßt
Ich gewinne den Eindruck dass du nicht weisst, was $_[0] ist.
Es ist das erste Element in @_ und somit das gleiche wie $nrDas ist richtig (auch wenn Kurt das bestreitet).
Jajaja ... könntet ihr beide vielleicht aufhören aus Rechthaberei Sachen aus dem Kontext zu reißen?
Das OP dreht sich *nicht* ums Param-Array @_ sondern um Default-Variable $_ in einer Schleife !!!
Anders gefragt: was ist an diesem Posting falsch und missverständlich? https://forum.selfhtml.org/?t=170971&m=1118632
Grüße
Kurt
Das OP dreht sich *nicht* ums Param-Array @_ sondern um Default-Variable $_ in einer Schleife !!!
und genau das hatte ich zu spät gesehen, da Beat das mit dem my() = @_ durcheinander gewürfelt hatte.
Struppi.
Kurtz gegrüßt
und genau das hatte ich zu spät gesehen, da ...
Struppi es ist nicht das erste mal das du etwas zu spät siehst und der Thread war zu dem Zeitpunkt wirklich sehr übersichtlich!
Was mich noch mehr annervt als dieses erst Klappe aufreißen und dann hingucken ist, dass ihr beide jetzt so ein Gezicke veranstaltet.
Guter Rat: http://www.oreilly.com/catalog/9780596001735/ gibts auch auf Deutsch!
so ich bin jetzt raus ...
Grüße
Kurt
Was mich noch mehr annervt als dieses erst Klappe aufreißen und dann hingucken ist, dass ihr beide jetzt so ein Gezicke veranstaltet.
was für ein Gezicke?
Du scheinst etwas oberempfindlich zu sein, was deine erste Reaktion auch deutlich macht.
Mir ist mittlerweile klar, dass es hier um zwei Dinge ging und die eine Aussage von beat war definitiv falsch und deine Antwort darauf war mißverständlich. Darum gibt es kein gezicke oder was du sonst noch hier siehst, es ist ja alles geklärt.
Der einzige der sich hier verhält wie im Kindergarten, mit persönlichen Beleidigungen und Rechthaberei, bist du und das tasächlich nicht zum erstenmal. Anstatt das du versuchst meine Antwort zu verstehen. Deren Kontext ich tasächlich falsch gesehen habe, was ich auch zugegeben habe, fühlst du dich persönlich auf den Schlips getreten - das ist Kindergarten.
Nochmal zum eruieren:
beat: » » Ich gewinne den Eindruck dass du nicht weisst, was $_[0] ist.
Es ist das erste Element in @_ und somit das gleiche wie $nr
»
Kurt » Nein, $_ ist eine Array-Referenz @$_ ...
Ich bezog dein nein auf die zweite Aussage, was Quatsch war, mir aber nicht aufgefallen ist, da ich mich mit der falschen Aussage von beat beschäftigt hatte.
Struppi.
We hat euch eigentlich gesagt, dass ihr an meine Würfel dürft?
mfg Beat
We hat euch eigentlich gesagt, dass ihr an meine Würfel dürft?
Kindergarten!
Kurtz gegrüßt
wieso? funktioniert doch ...
for $stoernr (1..20) {
push (@stoerliste,[$stoernr,$stoertyp,$stoertext,$stoersms,$stoerreserve1,$stoerreserve2,$stoerreserve3]);
}
print zaehler_von_nr(10);
sub zaehler_von_nr {
my ($nr) = @_;
my $zaehler = 0;
foreach (@stoerliste)
{
if (@$_[0] == $nr)
{
return $zaehler;
}
$zaehler++;
}
}
allerdings kann man das auch deutlich lesbarer schreiben...
sub zaehler_von_nr {
my ($nr) = @_;
my $zaehler = 0;
foreach my $stoer_ref (@stoerliste)
{
if ($stoer_ref->[0] == $nr)
{
return $zaehler;
}
$zaehler++;
}
}
Grüße
Kurt