$xNeTworKx: Hash lässt gleichwertige Schlüssel unter den Tisch fallen ?

Hallo,

Ich habe doch vor einiger Zeit mal gefragt, wie ich am besten Einträge nach Datum sortieren kann. Es funktioniert so weit alles so wie es soll. Gestern wurde ich aber von einem meiner Besucher darauf aufmerksam gemacht, daß wenn man 2 Termine mit dem gleichen Datum postet, eines davon nicht angezeit wird. Ich habe bereits die Fehlerquelle gefunden. Es ist diese Zeile :

foreach my $key(sort {$a <=> $b} keys %hash)

Wie bringe ich es fertig, daß er ALLE Schlüssel mit gleichem Wert anzeigt und nicht nur den ersten, den er findet ?

sub showparty   {
my $flyerurl = shift;
my @array = ();
my $partycounter = 0;
my $in = '';
my %hash;
print <<EOF;
<div style="position:absolute; top:95px">
<table style="border:0px; width:700px">
<colgroup>
<col width="5%">
<col width="15%">
<col width="40%">
<col width="30%">
<col width="10%">
</colgroup>
EOF
    open(FILE,"$partydata") or die "Cant open database : $!\n";
    local $/;
    $in = <FILE>;
    close FILE;
       while ($in =~ /<party>(.+?)</party>/sg)  {
       my $termin = $1;
             if ($termin =~ /<wann>(\d{2}).(\d{2}).(\d{4})</wann>/sg)  {
             push @array, $3.$2.$1, $termin;
             }
       }
       %hash = @array;

foreach my $key(sort {$a <=> $b} keys %hash)  {

if ($ip eq "$admin" || $ip eq "$moderator")  {
           print "<tr><td><a href="$url?action=deleteparty&partycounter=$partycounter"><img src="pics/delete.png" alt="del"></a></td>";
           }  else  {
           print "<tr><td>   </td>";
           }
           if ($hash{$key} =~ /<wann>(.+?)</wann>/)   {
           print "<td class="orangeright">$1</td>";
           }
           if ($hash{$key} =~ /<soundsystem>(.+?)</soundsystem>/)   {
           print "<td class="orangemiddle">$1</td>";
           }
           if ($hash{$key} =~ /<info>(.+?)</info>/)   {
           print "<td class="orangeleft">$1</td>";
           }  else  {
            print "<td> &nbsp </td>";
           }
           if ($hash{$key} =~ /<flyer>(.+?)</flyer>/)   {
           print "<td><a href="$url?action=flyer&url=$1">Flyer</a></td></tr>\n";
           }  else  {
           print "<td> &nbsp </td></tr>\n";
           }
$partycounter++;
}

$xNeTworKx.

  1. Hallo,

    Tach,

    Ich habe doch vor einiger Zeit mal gefragt, wie ich am besten Einträge nach Datum sortieren kann. Es funktioniert so weit alles so wie es soll. Gestern wurde ich aber von einem meiner Besucher darauf aufmerksam gemacht, daß wenn man 2 Termine mit dem gleichen Datum postet, eines davon nicht angezeit wird. Ich habe bereits die Fehlerquelle gefunden. Es ist diese Zeile :

    foreach my $key(sort {$a <=> $b} keys %hash)

    Nein. Es liegt in der Natur des Hashs, daß zu jedem Schlüssel genau ein Wert gespeichert wird.
    Wenn Du einen zweiten Wert unter dem selben Schlüssel ablegst, wird der erste ersetzt.

    Du könntest aber als Werte Listen verwenden, dann kannst Du zu einem Schlüssel die verschiedenen Werte in dieser Liste unterbringen.

    Andreas

    1. Hallo,

      Ich habe doch vor einiger Zeit mal gefragt, wie ich am besten Einträge nach Datum sortieren kann. Es funktioniert so weit alles so wie es soll. Gestern wurde ich aber von einem meiner Besucher darauf aufmerksam gemacht, daß wenn man 2 Termine mit dem gleichen Datum postet, eines davon nicht angezeit wird. Ich habe bereits die Fehlerquelle gefunden. Es ist diese Zeile :

      foreach my $key(sort {$a <=> $b} keys %hash)

      Nein. Es liegt in der Natur des Hashs, daß zu jedem Schlüssel genau ein Wert gespeichert wird.
      Wenn Du einen zweiten Wert unter dem selben Schlüssel ablegst, wird der erste ersetzt.

      Nein, vielleicht habe ich mich falsch ausgedrückt, oder du hast es falsch verstanden.
      Es exisiteren zB 3 Schlüssel-Wert Paare, aber er zeigt mir nur 2 Paare an, weil das eine Schlüssel-Wert Paar genau den selben Schlüsselnamen hat (= 20020720) Wenn ich jetzt $a <=> $b sortiere, wird nur einer der Schlüssel erkannt, und nicht beide, und das ist das Problem. Ich will aber, daß beide erkannt werden.

      1. Hallo,

        Nein, vielleicht habe ich mich falsch ausgedrückt, oder du hast es falsch verstanden.

        Ich denke, Du hast etwas falsch verstanden.
        Wenn Du folgenden Code ausprobierst:
        my %hash = (1,2,1,3,4,5);
        print join("\n",sort keys %hash);
        wird das Ergebnis
        1
        4
        lauten, weil eben keine zwei Hash-Einträge existieren können, die den gleichen Key haben.
        Abhilfe:
        Du könntest statt
        push @array, $3.$2.$1, $termin;
        auch

        $count++;
        push @array, $3.$2.$1.$count, $termin;
        machen, wobei $count halt noch vor der Schleife initialisiert(auf Null gesetzt) werden sollte.

        Damit hast Du sicher einen eindeutigen Schlüssel, und sortiert wird auch richtig.

        Grüße
          Klaus

        1. Hallo,

          Ich denke, Du hast etwas falsch verstanden.
          Wenn Du folgenden Code ausprobierst:
          my %hash = (1,2,1,3,4,5);
          print join("\n",sort keys %hash);
          wird das Ergebnis
          1
          4
          lauten, weil eben keine zwei Hash-Einträge existieren können, die den gleichen Key haben.
          Abhilfe:
          Du könntest statt
          push @array, $3.$2.$1, $termin;
          auch

          $count++;
          push @array, $3.$2.$1.$count, $termin;
          machen, wobei $count halt noch vor der Schleife initialisiert(auf Null gesetzt) werden sollte.

          Damit hast Du sicher einen eindeutigen Schlüssel, und sortiert wird auch richtig.

          Ok ich glaube so könnte ich es machen, danke auf jeden Fall.

          $xNeTworKx.

      2. Hallo,

        Nein. Es liegt in der Natur des Hashs, daß zu jedem Schlüssel genau ein Wert gespeichert wird.
        Wenn Du einen zweiten Wert unter dem selben Schlüssel ablegst, wird der erste ersetzt.

        Nein, vielleicht habe ich mich falsch ausgedrückt, oder du hast es falsch verstanden.

        Nein, DU hast noch nicht verstanden, wie ein Hash funktioniert.
        Oder WILLST Du es nicht verstehen?

        Es exisiteren zB 3 Schlüssel-Wert Paare, aber er zeigt mir nur 2 Paare an, weil das eine Schlüssel-Wert Paar genau den selben Schlüsselnamen hat (= 20020720) Wenn ich jetzt $a <=> $b sortiere, wird nur einer der Schlüssel erkannt, und nicht beide, und das ist das Problem. Ich will aber, daß beide erkannt werden.

        Jeder Schlüssel kann genau einmal vorkommen! Kapier es halt endlich.
        Wenn Du erst (key1, value1) in den Hash einfügst und dann (key1, value2), dann existiert im Hash nur (key1, value2), da (key1, value1) überschrieben wurde.

        Andreas

        1. Jeder Schlüssel kann genau einmal vorkommen! Kapier es halt endlich.

          Oh verzeihen sie vielmals eure hohe Eminenz, daß mein minderwertiges Wissen nicht eurer Weisheit entspricht.

          $xNeTworKx.

          1. Hi!

            Jeder Schlüssel kann genau einmal vorkommen! Kapier es halt endlich.

            Oh verzeihen sie vielmals eure hohe Eminenz, daß mein minderwertiges Wissen nicht eurer Weisheit entspricht.

            Was soll der Scheiss? Er hat Dir gesagt, was Sache ist, aber Du behauptest, er haette Dein Problem nicht verstanden. Er sagt Dir nochmal, was Sache ist, aber statt mal drueber nachzudenken, faengst Du an, rumzuflamen. Dann frag doch besser in einem der Heise-Foren, vielleicht wird Dir da ja besser geholfen.

            Wenn es so waere, wie Du sagst, dass also erst beim Sortieren der Fehler entsteht, dann koenntest Du den Hash-Inhalt ja einfach mal unsortiert ausgeben und sehen, was da rauskommt. Dann mach mal, ich bin gespannt.

            So long

            --
            Wipe Info uses hexadecimal values to wipe files. This provides more security than wiping with decimal values.
                -- Norton SystemWorks 2002 Professional Edition User's Guide
                   (ftp://ftp.symantec.com/public/english_us_canada/products/norton_systemworks/ver5.0/nswpro2002.pdf)
                   page 158

            1. Hi,

              Jeder Schlüssel kann genau einmal vorkommen! Kapier es halt endlich.

              Oh verzeihen sie vielmals eure hohe Eminenz, daß mein minderwertiges Wissen nicht eurer Weisheit entspricht.

              Was soll der Scheiss? Er hat Dir gesagt, was Sache ist, aber Du behauptest, er haette Dein Problem nicht verstanden. Er sagt Dir nochmal, was Sache ist, aber statt mal drueber nachzudenken, faengst Du an, rumzuflamen. Dann frag doch besser in einem der Heise-Foren, vielleicht wird Dir da ja besser geholfen.

              1. Ich zitiere mal Andreas' Posting:

              Nein. Es liegt in der Natur des Hashs, daß zu jedem Schlüssel genau ein Wert gespeichert wird.
              Wenn Du einen zweiten Wert unter dem selben Schlüssel ablegst, wird der erste ersetzt.

              Du könntest aber als Werte Listen verwenden, dann kannst Du zu einem Schlüssel die verschiedenen Werte in dieser Liste unterbringen.

              Jetzt werd ich dir mal erzählen wie ich das verstanden habe:
              Ich habe daraus gelesen, daß er meinte, daß ich unter einem HashSchlüssel nur einen Wert speichern kann, also nur Name=wert1, und nicht Name=Wert1Wert2 oder was auch immer.

              Wenn man den Satz mal genauer ansieht:
              Wenn Du einen zweiten Wert unter dem selben Schlüssel ablegst, wird der erste ersetzt.

              Das "der erste" könnte sich auch auf "Wert" beziehen, und so habe ich das zuerst auch gelesen (= grammatikalisch zweideutig).

              Und deswegen muss ich mich also von dir und AndreasW anpfauchen lassen? Das kann man auch ganz anders sagen.
              Ausserdem habe ich nur höflich vermutet, daß mein Problem vielleicht falsch verstanden wurde, eben weil der obige Satz zweideutig ist und deswegen meine Vermutung.

                1. Ich zitiere mal Andreas' Posting:

                Nein. Es liegt in der Natur des Hashs, daß zu jedem Schlüssel genau ein Wert gespeichert wird.
                Wenn Du einen zweiten Wert unter dem selben Schlüssel ablegst, wird der erste ersetzt.

                Du könntest aber als Werte Listen verwenden, dann kannst Du zu einem Schlüssel die verschiedenen Werte in dieser Liste unterbringen.

                Jetzt werd ich dir mal erzählen wie ich das verstanden habe:
                Ich habe daraus gelesen, daß er meinte, daß ich unter einem HashSchlüssel nur einen Wert speichern kann, also nur Name=wert1, und nicht Name=Wert1Wert2 oder was auch immer.

                Na wunderbar, genau das war ja auch gemeint.

                Mit dem zweiten Teil meinte er dann, dass Du mehrere Werte in ein Array stecken kannst und eine Referenz auf dieses Array dann als Wert in den Hash schreiben. Etwa
                  $hash{'datum'} = [$wert1, $wert2];    # genau die Art der Klammern beachten!
                Mit @{$hash{'datum'}} bekommst Du dann ein normales Array zurueck, die die beiden Werte enthaelt. Siehe dazu perldoc perllol und perldoc perldsc.

                Wenn man den Satz mal genauer ansieht:
                Wenn Du einen zweiten Wert unter dem selben Schlüssel ablegst, wird der erste ersetzt.

                Das "der erste" könnte sich auch auf "Wert" beziehen, und so habe ich das zuerst auch gelesen (= grammatikalisch zweideutig).

                Gut, so war es ja auch gemeint: Der Wert, der urspruenglich unter dem Schluessel abgelegt war, wird durch den neuen ersetzt.
                (Waere gemeint gewesen, dass der erste *Schluessel* ersetzt wird, die Schluessel aber sowieso die gleichen sind, haette sich dann ja effektiv nichts getan. Der Satz waere dann voellig sinnlos gewesen.)

                Nun frage ich mich, wenn Du die Saetze schon semantisch richtig verstanden hast, wo dann das Problem lag? Deinen Fehler hat Andreas damit genau gefunden, was hat Dich also zu der Vermutung veranlasst, jemand hat was falsch verstanden? Dass Andreas davon genervt war, ist nur verstaendlich.

                Und deswegen muss ich mich also von dir und AndreasW anpfauchen lassen? Das kann man auch ganz anders sagen.

                Ganz ruhig. Zieh Dir erst mal ne Kanne Kaffee oder ne Packung Traubenzucker rein, und dann denk nochmal in Ruhe drueber nach. Und probier einfach mit ein paar Testscripts rum, wie Hashs funktionieren, dann wird das schon. Wenn Du mit den komplexeren Datenstrukturen aus perldsc rumprobierst, empfiehlt sich
                  use Data::Dumper;
                  print Dumper(%hash);
                um sich die Struktur anzusehen.

                So long

                --
                Was ist der Unterschied zwischen "Jurassic Park" und Mircosoft? Bei dem einen macht ein Verrückter Geschäftsmann mit Biestern, die schon längst ausgestorben sein sollten, ein Vermögen, und das andere ist ein Film von Steven Spielberg.

      3. Aloha!

        Nein, vielleicht habe ich mich falsch ausgedrückt, oder du hast es falsch verstanden.

        Sicher nicht. :)

        Es exisiteren zB 3 Schlüssel-Wert Paare, aber er zeigt mir nur 2 Paare an, weil das eine Schlüssel-Wert Paar genau den selben Schlüsselnamen hat (= 20020720) Wenn ich jetzt $a <=> $b sortiere, wird nur einer der Schlüssel erkannt, und nicht beide, und das ist das Problem. Ich will aber, daß beide erkannt werden.

        Wenn du sowas machst:

        $termin['20020719']="Hash ausprobieren";
        $termin['20020720']="Selfforum besuchen";
        $termin['20020720']="Kartoffeln kaufen";

        Na, was wird dann passieren? Die dritte Zeile greift auf den _gleichen_ Schlüssel zu wie die zweite Zeile, also wird die dritte Zeile den Inhalt des Termins am 20.7.2002 bestimmen, und nicht die zweite _und_ dritte Zeile gleichzeitig erscheinen.

        Es kann immer nur _einen_ Schlüssel gleichen Namens geben. Wäre das nicht der Fall: Wie soll man dann einerseits bestehende Werte ändern können, und andererseite: Welcher Termin wäre denn gemeint, wenn ich mit echo $termin['20020720']; wissen will, was heute zu tun ist?

        Das, was du willst, läßt sich mit mehreren eindimensionalen oder einem mehrdimensionalen Array lösen:

        $termin[23]['aktion']="Selfforum besuchen";
        $termin[23]['datum']="20020720";

        $termin[24]['aktion']="Kartoffeln kaufen";
        $termin[24]['datum']="20020720";

        Wenn du dieses Array sortieren willst, nimm array_multisort(). Eventuell ist es dazu zwingend notwendig, den Index umzudrehen:

        $termin['aktion'][23]...
        $termin['datum'][23]...

        Du kannst aber genauso mit zwei Arrays arbeiten, das macht absolut keinen Unterschied:
        $datum[23]=...
        $aktion[23]=...

        - Sven Rautenberg

        1. Aloha!

          [Zeugs...]

          Wenn du dieses Array sortieren willst, nimm array_multisort(). Eventuell ist es dazu zwingend notwendig, den Index umzudrehen:

          [mehr Zeugs...]

          Jaja, eine schöne PHP-Lösung, die es da gibt. Nur leider für Perl etwas unpassend. :)

          Allerdings ist die Vorgehensweise durchaus kopierbar. ;)

          - Sven Rautenberg

        2. $termin['20020719']="Hash ausprobieren";
          $termin['20020720']="Selfforum besuchen";
          $termin['20020720']="Kartoffeln kaufen";

          Na, der Effekt ist logisch. Du willst einen "hash of lists" benutzen.