Jonas: 2 Arrays in bestimmten Feldern vergleichen

Hi

Also, da ich hier schon oft schnelle Hilfe fand, hoffe ich, dass irgend ein Perl-Master mir bei meinem Problem (erneut) weiterhelfen kann ;)

Zu besagtem Problem:

Ich habe zwei Arrays, die folgendermassen aufgebaut sind.

"newarray":
id1|name1|datum1|autor1
id2|name2|datum2|autor2

"oldarray":
oid1|oname1|odatum1|oautor1
oid2|oname2|odatum2|oautor2

Das Ganze kommt aus einem .txt-File, das als Datenbank erhalten muss.

Nun will ich die beiden Arrays bezüglich das Feldes name# und oname# vergleichen. Dabei sollten Werte aus oldarray, die in newarray erhalten sind, durch die Werte von newarray ersetzt werden. Werte, die es in oldarray gibt, aber in newarray nicht, sollen beibehalten werden. Zu gut deutsch: oldarray soll mit newarray ergänzt werden, ohne doppelte Einträge bezüglich des Feldes name# bzw. oname#.

Mein spontaner Ansatz waren verschachtelte foreach-Schleifen, wobei natürlich jedes Element des aus der Datei stammenden Arrays erst mittels split() getrennt werden muss, damit ich direkt zum Vergleich auf die Werte der "Spalte" name zugreifen kann.

Irgendwie werde ich aber das Gefühl nicht los, dass ich mit den verschachtelten foreach-schlaufen nicht unbedingt die schnellste, ressourcenschonendste und eleganteste lösung habe!

Kennt da jemand einen klügeren Ansatz? (Ich hoffe doch ;))

Gruss und Dank

Jonas

  1. Tag Jonas.

    Nun will ich die beiden Arrays bezüglich das Feldes name# und oname# vergleichen. Dabei sollten Werte aus oldarray, die in newarray erhalten sind, durch die Werte von newarray ersetzt werden. Werte, die es in oldarray gibt, aber in newarray nicht, sollen beibehalten werden. Zu gut deutsch: oldarray soll mit newarray ergänzt werden, ohne doppelte Einträge bezüglich des Feldes name# bzw. oname#.

    Kennst du die perlfaq4, Abschnitt Arrays?

    [dsf 3.6]
    Siechfred

    --
    »Sie kochten heimlich mit Wasser und tranken öffentlich Wein.«
    1. Hi

      Kennst du die perlfaq4, Abschnitt Arrays?

      Hmm.. du wirst lachen, aber genau dort habe ich schon mal gesucht. Habe nix passendes zu meinem Problem entdeckt :O
      Kann aber durchaus sein, dass ich das Ganze in englischer Sprache nicht korrekt übersetzten konnte...

      Besonders die Sache, dass es sich ja nicht im Arrays handelt, sondern um Arrays, die wiederum in einzelne "Felder" mittels | unterteilt sind und nur die Werte aus einem dieser Felder zum Vergleich herangezogen werden soll, macht mir etwas Probleme... Die ganze Sache jedesmall mittels split() in ein "temporäres" Array zu spalten um dann direkt auf das gesuchte Element zum Vergleich zugreifen zu können, empfinde ich als ein wenig unnötig kompliziert. Da stellt sich mir eben die Frage als Perl-n00b, ob es nicht auch eine bessere Möglichkeit dafür gibt.

      Gruss und Dank

      Jonas

      1. Nachtrag:

        Habe nun folgendes versucht:

        @array1 = ("test1|name1|b1","test2|name2|b2","test3|name3|b3","test4|name4|b4","test5|name5|b5");
        @array2 = ("test12|name1|b1","test22|name22|b2","test32|name3|b3","test42|name4|b4","test52|name5|b5");

        @union = @intersection = @difference = ();
            %count = ();
            foreach $element (@array1, @array2) { $count{$element}++ }
            foreach $element (keys %count) {
         push @union, $element;
         push @{ $count{$element} > 1 ? @intersection : @difference }, $element;
            }

        Also @union erhalte ich nun folgende Elemente zurück:
        test1|name1|b1
        test52|name5|b5
        test22|name22|b2
        test5|name5|b5
        test2|name2|b2
        test3|name3|b3
        test32|name3|b3
        test42|name4|b4
        test4|name4|b4
        test12|name1|b1

        Logisch, keines der Elemente ist doppelt vorhanden.

        Jedoch sollte genau diese Operation nur auf die "name" Felder angewandt werden.

        1. gudn tach Jonas!

          ich wuerde es mal mit diesem ansatz versuchen (ungetestet):

          %count=();
          foreach $element (@array_neu, @array_alt){
           if($element=~/[1]*|([^|]*)|/){ # extrahiere name (hier 2. spalte)
            # falls name vorher noch nicht aufgetaucht ist, speichere $element
            $count{$1}=$element unless exists $count{$1};
           }
          }

          prost
          seth


          1. ^| ↩︎

          1. %count=();
            foreach $element (@array_neu, @array_alt){
            if($element=~/[1]*|([^|]*)|/){ # extrahiere name (hier 2. spalte)
              # falls name vorher noch nicht aufgetaucht ist, speichere $element
              $count{$1}=$element unless exists $count{$1};
            }
            }

            Die Idee scheint mir wirklich gut. Aber leider klappt das Ganze in der Praxis nicht, da $element=~/[2]*|([^|]*)|/ als Rückgabe den ganzen Inhalt eines Feldes und nicht nur die zweite Spalte liefert...

            Leider sehe ich den Fehler absolut nicht.....


            1. ^| ↩︎

            2. ^| ↩︎