Matze: ActionScript3 / XMLList nach Wert in Attribut durchsuchen

Hallo!

Ich habe ein Problem mit der "Verknüpfung" von 2 XML-Dateien.
Die erste XML-Datei enthält Beschreibungen und Eigenschaften für verschiedene Artikel.
Z.B.

<art id="1">  
    <farbe name="rot" />  
    <farbe name="grün" />  
    <farbe name="blau" />  
</art>  
<art id="2">  
    <farbe name="gelb" />  
    <farbe name="schwarz" />  
    <farbe name="weiß" />  
    <farbe name="grau" /> <!-- soll ignoriert werden -->  
</art>

Die zweite Datei enthält eine Liste mit allen verfügbaren Farben.
Z.B.

<farbe name="schwarz" />  
<farbe name="weiß" />  
<farbe name="gelb" />  
<farbe name="rot" />  
<farbe name="grün" />  
<farbe name="blau" />  
<farbe name="lila" />  
<farbe name="neonbraun" />

Jetzt würde ich gern die Farben so Filtern, dass nur die angezeigt werden, die auch in der zweiten Datei gefunden werden.

Mit Pseudo-Code könnte das so aussehen:

für jede ( Farbe aus XMLList 1 )
{
    prüfe ob (Attribut 'name' der Farbe aus XMLList 1
    identisch mit dem Attribut 'name' _irgend einer_ Farbe aus XMLList 2 ist)
    {
        und dann tue etwas sinnvolles
    }
}

Die einzige Möglichkeit, die mir einfällt, ist, in 2 verschachtelten for-Schleifen jedes Element aus der ersten Datei mit jedem Element aus der zweiten Datei zu vergleichen.
Das erscheint mir aber ziemlich umständlich.

Jemand eine Idee wie ich das einfacher lösen könnte?

Danke und Grüße, Matze

  1. Die einzige Möglichkeit, die mir einfällt, ist, in 2 verschachtelten for-Schleifen jedes Element aus der ersten Datei mit jedem Element aus der zweiten Datei zu vergleichen.
    Das erscheint mir aber ziemlich umständlich.

    Jemand eine Idee wie ich das einfacher lösen könnte?

    Naja, wahrscheinlich ist es das.
    Allerdings macht es wahrscheinlich Sinn die zweite Datei nur einmal einzulesen und das Resultat abgespeckt irgendwo in ein Array zu werfen, so dass man nicht wieder und wieder eine Datei ausliest und parst, sondern nur einmal.

    Oder aber es gelingt dir automatisch eine RegEx daraus zu formulieren, das wäre mir persönlich aber zu komplex.

    --
    sh:( fo:| ch:? rl:( br:& n4:& ie:{ mo:} va:) de:µ_de:] zu:) fl:( ss:| ls:[ js:(
  2. hi,

    Die einzige Möglichkeit, die mir einfällt, ist, in 2 verschachtelten for-Schleifen jedes Element aus der ersten Datei mit jedem Element aus der zweiten Datei zu vergleichen.
    Das erscheint mir aber ziemlich umständlich.

    Naja, die Dateien musst Du so oder so einlesen. Und da ist jetzt die Datensruktur entscheidend, die Du daraus machst. In Perl wären das bei mir Hashes mit Referenzen, damit wäre die Sache mit einem Schleifendurchlauf erledigt.

    Hotti

    1. Guten Morgen Hotti,

      Naja, die Dateien musst Du so oder so einlesen. Und da ist jetzt die Datensruktur entscheidend, die Du daraus machst. In Perl wären das bei mir Hashes mit Referenzen, damit wäre die Sache mit einem Schleifendurchlauf erledigt.

      könntest du mir ein Beispiel geben wie man sowas macht?
      In Perl würde mir wohl reichen, ich denk ich würde es selbst schaffen das Ganze dann auf ActionScript zu übertragen.

      Danke und Grüße, Matze

      1. hi,

        könntest du mir ein Beispiel geben wie man sowas macht?

        Mein Ansatz:

          
        # aus Datei die Grundfarben  
        # aus Array ['swa','wei','glb','rot','grn','blu','lil','neo'] einen hash gemacht  
        my $farbs = {  
            'swa' => 1,  
            'rot' => 1,  
            'grn' => 1,  
            'glb' => 1,  
            'wei' => 1,  
            'blu' => 1,  
            'lil' => 1,  
            'neo' => 1,  
        };  
          
        # aus Datei die Artikel  
        # hash mit id als key  
        my $arts = {  
            1 => {name => ['rot','grn','blu']},  
            2 => {name => ['glb','swa','wei','grr']},  
        };  
          
        print "Prfe Artikel:\n\n";  
        foreach my $ak(keys %{$arts}){  
            print "Artikel $ak:\n";  
            # innere Schleife über Array [name]  
        }  
        
        

        Hotti

        1. Hallo Hotti,

          So genau hab ich es aber noch nicht verstanden.
          Genauer gesagt versteh ich grad nicht was in der foreach-Schleife passiert.
          Das liegt allerdings an meinem nicht vorhandenen Wissen über PERL.

          Es ist wohl doch nicht so einfach zu übersetzen wie ich dachte :(

          Ich schau mal was ich daraus machen kann.

          Danke und Grüße, Matze

          1. hi,

            Genauer gesagt versteh ich grad nicht was in der foreach-Schleife passiert.

            soso ;-)
            Na dann guck mal :P

              
            # aus Datei die Artikel  
            # hash mit id als key  
            my $arts = {  
                1 => {name => ['rot','grn','blu']},  
                2 => {name => ['glb','swa','wei','grr']},  
            };  
              
            print "Prüfe Artikel:\n\n";  
            foreach my $ak(keys %{$arts}){  
                print "Artikel-ID $ak:\n";  
                # innere Schleife über Array [name]  
                foreach my $farbe(@{$arts->{$ak}->{name}}){  
                    print "$farbe\n";  
                }  
            }  
            
            

            Ausgabe:
            Prüfe Artikel:

            Artikel-ID 1:
            rot
            grn
            blu
            Artikel-ID 2:
            glb
            swa
            wei
            grr

            Ok, ok, es sind 2 Schleifen. In der Inneren ist nur noch zu prüfen, ob die Farben im anderen Struct verfügbar sind, das kriegste jetzt hin ;-)

            Hotti

            1. Nochwas ;

              guck mal bei CPAN, was es so an XML-Parsern gibt zum Einlesen von XML-Dateien. Schau Dir die Datenstrukturen an, die ein solcher Parser erzeugt, die werden ähnlich aussehen, wie ich notiert habe (use Data::Dump;),

              use Coffee;
              $co = Coffee->new('Sauwetter');
              $Erfolg = $co->{trinken}->{nachdenken}->{tippen};

              Hotti

              1. guck mal bei CPAN, was es so an XML-Parsern gibt zum Einlesen von XML-Dateien. Schau Dir die Datenstrukturen an, die ein solcher Parser erzeugt, die werden ähnlich aussehen, wie ich notiert habe (use Data::Dump;),

                Nunja, da ich das ganze in ActionScript umsetzen muss interessiert mich CPAN eher weniger.
                Ich weiß ja wie die Daten aussehen nachdem ich die XML eingelesen habe.
                Es geht mir hier nur um den Vergleich der Einträge in den Dateien.

                Ich werde wohl die 2 Schleifen nehmen und damit zufrieden sein, dass es nicht "einfacher" geht. Oder ich schreibe mir eine Funktion isInXML() die genau das macht. Eventuell auch rekursiv.
                Vielleicht brauch ich sowas ja nochmal.

                Grüße, Matze

                1. hi,

                  Ich werde wohl die 2 Schleifen nehmen und damit zufrieden sein, dass es nicht "einfacher" geht.

                  Definiere "Einfacher":

                    
                  print "Prfe Artikel....\n\n";  
                  foreach my $ak(keys %{$arts}){  
                      print "Artikel-ID $ak:\n";  
                      my $anz_in_arts = @{$arts->{$ak}->{name}};  
                      my $treffer = scalar grep{$farbs->{$_}} @{$arts->{$ak}->{name}};  
                      printf "Anzahl Farben: %u, davon Erlaubt: %u \n", $anz_in_arts, $treffer;  
                  }  
                  
                  

                  Prfe Artikel....

                  Artikel-ID 1:
                  Anzahl Farben: 3, davon Erlaubt: 3
                  Artikel-ID 2:
                  Anzahl Farben: 4, davon Erlaubt: 3
                  Artikel-ID 3:
                  Anzahl Farben: 1, davon Erlaubt: 0

                  Wobei auch hier implizit eine Iteration erfolgt. Eine explizit notierte Schleife tuts auch und ist übersichtlicher.

                  Hotti

                  1. Definiere "Einfacher":

                    Vermutlich ist es einfach mein persönliches Problem, dass ich für sowas gern eine Funktion hätte.
                    Seitdem ich mich mit Programmiersprachen beschäftige, ärgert mich regelmäßig, dass es keine Funktionen zur Suche nach einem Wert in einem Array gibt.
                    Ich bin irgendwie der Überzeugung, dass man das oft braucht und ärgere mich dann umso mehr wenn ich sie jedesmal selbst schreiben muss.

                    Wahrscheinlich sind 2 Schleifen völlig ok und ich hab einfach nur eine Blokade im Kopf.

                    Ich danke dir für deine Hilfe!

                    Grüße, Matze

                    1. hi Matze,

                      Ich bin irgendwie der Überzeugung, dass man das oft braucht und ärgere mich dann umso mehr wenn ich sie jedesmal selbst schreiben muss.

                      Da haste Recht. Btw., Es gibt neben map() und grep() auch noch den sogenannten hash-slice in Perl. Damit kannst du z.B. mit einer Anweisung ein komplettes Array an Keys löschen oder zuweisen und viell. auch noch mehr... (nachlesen).

                      Wahrscheinlich sind 2 Schleifen völlig ok

                      Sind die auch. Du hast eine lange und eine kurze Schleife, die lange brauchst Du sowieso. Es ist manchmal besser und übersichtlicher eine explizite Schleife selbst zu notieren, als map() oder grep() die Iteration zu überlassen. Z.B. kannst Du eine eigenen Schleife auch mal vorzeitig abbrechen, wenn Du das gefunden hast, was Du wolltest, map() hingegen marschiert immer durch.

                      Ich danke dir für deine Hilfe!

                      Gerne. Ich bin Handwerker und wenn ich einmal den Hammer in der Hand habe, kann ich auch dem Nachbarn mal kurz helfen ;-)

                      Hotti :P

            2. Hey Hotti,

              Ok, ok, es sind 2 Schleifen. In der Inneren ist nur noch zu prüfen, ob die Farben im anderen Struct verfügbar sind, das kriegste jetzt hin ;-)

              ist das nicht dasselbe was ich als Lösung vorgeschlagen hatte?
              Genau die 2 Schleifen wollte ich doch aber umgehen.
              Dachte es gibt da vielleicht etwas kürzeres als jedesmal alle Elemente aus Datei 1 gegen alle Elemente aus Datei 2 zu vergleichen.

              Grüße, Matze

  3. Hallo,

    ich würde es so machen:

    1.) eine Funktion schreiben (oder das Array-Objekt um eine Methode erweitern), welche ein Array auf einen Wert prüft und im Erfolgsfall "true" zurückgibt.

    2.) lies die Datei mit den verfügbaren Farben in ein Array ein

    3.) beim Durchlaufen der Farben aus der ersten XML-Datei prüfst Du anhand der o.g. Funktion, ob die Farbe existiert

    Grüße Basti

    1. Hallo Basti,

      2.) lies die Datei mit den verfügbaren Farben in ein Array ein

      das halte ich für Unsinn. Ich kann die XMLList auch direkt durchlaufen ohne die Daten vorher umzukopieren.
      Deine erwähnte Array-Funktion könnte ich also genauso gut durch eine XML-Funktion ersetzen.

      In dem aktuellen Projekt brauch ich das aber nur 1 mal. Also werd ich wohl 2 Schleifen nehmen und fertig.

      Trotzdem Danke für den Vorschlag!

      Grüße, Matze