Marko Schilde: $string elementof @array?

Hi,

Ich suche einen möglichst effektiven Weg um herauszufinden, ob ein bestimmter String in einem Array als Element vorkommt. Sicher, man kann mit foreach und einem if-Vergleich arbeiten, aber es muss doch einen kürzeren/effektiveren Weg geben??

Der mir am logischsten erscheinende Ansatz if ($string =~ /@array/g) führt leider zu nichts :-(

-M

  1. Hallo!

    Ich suche einen möglichst effektiven Weg um herauszufinden, ob ein bestimmter String in einem Array als Element vorkommt. Sicher, man kann mit foreach und einem if-Vergleich arbeiten, aber es muss doch einen kürzeren/effektiveren Weg geben??

    Standardproblem. Effektiver geht es *kaum*. Siehe <http://www.Activestate.com/ActivePerl/docs/lib/Pod/perlfaq4.html#how can i tell whether a list or array contains a certain element>

    Der mir am logischsten erscheinende Ansatz if ($string =~ /@array/g) führt leider zu nichts :-(

    Logisch? Naja, nicht wirklich.

    So lange

  2. Hi,

    aber es muss doch einen kürzeren/effektiveren Weg geben??

    Keine Ahnung, ob effektiver, aber kuerzer allemal ,)

    $listen_skalar = join("",@liste);

    if($listen_skalar =~ /ausdruck/g)
    {
    $vorhanden = 1;
    }

    mfg
    CK1

    1. Hi CK1,

      »»$listen_skalar = join("",@liste);
      »»if($listen_skalar =~ /ausdruck/g) {
      »»   $vorhanden = 1;
      »»}

      Das hab ich auch schon mal so gemacht, allerdings auch feststellen müssen, daß sich da schnell einige Fallen ergeben (also ist folgendes mehr für`s Archiv!? bzw. als Ergänzung zu betrachten. Also nicht denken, ich würde jetzt den "Besserwisser" raushängen lassen wollen. Nein, ich möchte nur meine Erfahrungen teilen ;-).
      a) Wenn das Element den Ausdruck als Teilstring enthält, wird $vorhanden ebenfalls 1. Man sollte also die Delimiter (bei join angegebnen) in den Suchausdruck einbeziehen. Wenn die Elemente des Arrays nur ganze Wörter sind, kann man auch auf Wortgrenzen überprüfen, muss allerdings auch dabei beachten, daß \b normalerweise auch Umlaute für eine Wortgrenze hält (sch*** Amis ;-)
      b) (unwahrscheinlicher :-) Falls Dein Ausdruck zufällig "BlaBlaBlub" sein sollte, und im Array ein Element BlaBla und ein Element Blub existiert, führt das auch zu einem Treffer. Sprich, Du musst unter Kontrolle haben, was im Suchausdruck und im Array enthalten sein kann (->Usereingaben?). Der Delimiter für join sollte also möglichst nie in Elementen vorkommen.

      Gruß AlexBausW

      P.S.: Noch eine kleine Ergänzung: Wenn a) und b) abgehakt sind, könnte man auch zählen, wie oft Ausdruck vorkommt (als Nebenprodukt, da man ja nie weis, ob man`s nicht mal braucht ;-):
      while ($listen_skalar =~ /$delimiter$ausdruck$delimiter/g) {
        $vorhanden += 1;
      }
      Geht natürlich auch ähnlich wie in der FAQ:
      foreach (@array) { $temp{$_}++; } #ermittelt Anzahl gleicher Elemente
      @array = keys(%temp); # eliminiert mehrfachvorkommende Elemente (latürnich nur wenn gewünscht ;-)
      foreach (@array) { print $_.": ".$temp{$_}."\n"; }

      P.P.S.: Wenn ich es nicht gerade gestern erst selbst so in ein Skript eingebaut hätte, hätte ich es auch nicht gepostet :-)

  3. Hier vielleicht noch eine handlichere Variante:

    Erst ein kleines Unterprogramm:

    sub scan {
    my $x = shift;
    foreach (@array) {if ($x eq $_) {return TRUE;}}
    return FALSE;
    }# end sub

    Und das kannst du jetzt mit deinem Element aufrufen.
    Z.B.

    if (&scan("Boris")) {print "Boris ist drin"}
    else {print "Boris ist nicht drin"}

    @array musst du im Unterprogram natürlich noch anpassen.

    Gruß
    Cruz