brain: mehrdimensionales Array abfragen

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

  1. 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  
    
    
  2. 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 ){

    $_ ist eine Rererenz

    $_->[0] == 1 and be_happy();

    oder

    @{$_}[0] == 1 and be_happy();

    }

    mfg Beat

    1. 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

      1. 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

        1. 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

      2. 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.

        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.

        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]  
          }  
          
          
          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.
            
          2. 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.

          3. 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

            1. 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.

            2. 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

              1. 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

    2. 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.

      1. 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

        1. 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.

      2. 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

        Das 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

        1. 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.

          1. 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

            1. 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.

          2. We hat euch eigentlich gesagt, dass ihr an meine Würfel dürft?

            mfg Beat

            1. We hat euch eigentlich gesagt, dass ihr an meine Würfel dürft?

              Kindergarten!

  3. 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