Lena: Reihenfolge von assoziativen Arrays

Hallo zusammen :)

ich habe folgende Frage:

Füge ich einem assoziativen Array Wert-Schlüssel-Paare hinzu, sind diese dann _immer_ in der Reihenfolge, in der ich sie reingeschupst habe? - Wenn ich sie zum Beispiel per foreach oder print_r ausgebe... - Oder ist dies ein rein zufälliges Verhalten, dass unter Umständen anders ist?

In der PHP-Doku habe ich leider nichts gefunden.

Weiß hier jemand näheres?

Ein Gruß
Lena

  1. Hi,

    Füge ich einem assoziativen Array Wert-Schlüssel-Paare hinzu, sind diese dann _immer_ in der Reihenfolge, in der ich sie reingeschupst habe? - Wenn ich sie zum Beispiel per foreach oder print_r ausgebe... - Oder ist dies ein rein zufälliges Verhalten, dass unter Umständen anders ist?

    In der PHP-Doku habe ich leider nichts gefunden.

    http://www.php.net/manual/en/language.types.array.php sagt: "Arrays are ordered."

    MfG ChrisB

    --
    „This is the author's opinion, not necessarily that of Starbucks.“
  2. Hallo,
    also assoziativen Arrays spricht man allgemein (d.h. datenstrukturtechnisch) keine Reihnfolge zu. Deswegen sollte man sich in PHP auch nicht auf die Reihnfolge verlassen.

    Programmiert man selber ein assoziatives Array, verwendet man meistens eine Hashtable für die Realisierung. Dies ist eigentlich nichts weiteres als ein normales Array (mit numerischen Indizes) und die Schlüssel werden mittels Hashfunktion auf die numerischen Indizes abgebildet (eine Hashfunktion nimmt den Key (String) und macht daraus eine Zahl mit den unterschiedlichesten Operationen)

    Gibt man diese Hashtable nun in einer Reihnfolge aus, so geht man normalerweise normal das Array durch. Da aber Schlüssel auf die unterschiedlichsten Indizes abgebildet werden (z.B. 'a' auf 5, 'b' auf 18, 'abc' auf 2 usw.) hat man weder eine Reihnfolge bzgl. der Keys (der Zeichenkette) noch der Reihnfolge des Einfügens.

    In PHP kann es natürlich anders gelöst sein, dies hätte aber Geschwindigkeitsnachteile.

    Grüße
    Klaus

    1. Hallo,
      hier noch ein Link zum Thema Hashtable/Hashmap:
      http://guxx.de/2007/11/11/assoziative-arrays-als-hashmaps-selbst-verwalten/

      Grüße
      Klaus

      1. Moin!

        hier noch ein Link zum Thema Hashtable/Hashmap:
        http://guxx.de/2007/11/11/assoziative-arrays-als-hashmaps-selbst-verwalten/

        Der Artikel befaßt sich nicht mit PHP-Arrays, sondern wirft diese Arrays in der Einleitung leider undifferenziert in einen Topf mit Perl-Hashes, welche eine komplett andere Datenstruktur sind.

        PHP-Arrays:

        • sind immer definiert sortiert
        • können numerische und String-Keys mischen
        • verhalten sich deshalb eher wie eine Liste, auf deren Elemente man auch direkt über den Key zugreifen kann.

        Diese Datenstruktur bietet einige nette Vorteile, die man aber erst erkennt, wenn man sich etwas intensiver damit beschäftigt hat.

        - Sven Rautenberg

        1. Hi Sven,

          jetzt bin ich überrascht: IMHO nach war ein (perl-) hash ein assoziatives Array (auch selfhtml sagt: "<http://de.selfhtml.org/perl/sprache/hashes.htm@title=Ein assoziativer Array, in Perl als Hash bezeichnet(...)>"

          Und gefragt war doch nach "assoziativen Arrays" - nicht nach PHP Arrays. Dass in PHP sogar assoziative Arrays sortiert sind, stellt lediglich eine besondere Implementierung unter PHP dar - eine generelle Forderung dieser Art gibt es für assoziative Arrays, soweit ich weiß, aber nicht.

          Grüße,
          Richard

          1. Moin!

            jetzt bin ich überrascht: IMHO nach war ein (perl-) hash ein assoziatives Array (auch selfhtml sagt: "<http://de.selfhtml.org/perl/sprache/hashes.htm@title=Ein assoziativer Array, in Perl als Hash bezeichnet(...)>"

            Perl ist nicht PHP. Deshalb sind Zitate, die sich auf Perl beziehen und aus einer Zeit resultieren, die lange vor der Verbreitung von PHP liegt, wenig sinnvoll zur Erörterung der hier gestellten Frage.

            Und gefragt war doch nach "assoziativen Arrays" - nicht nach PHP Arrays.

            Der Titel des Postings lautet: "(PHP) Reihenfolge von assoziativen Arrays".

            Also wird es sich wohl um PHP drehen, zumal das OP sogar explizit PHP-Funktionen nennt und nirgendwo impliziert, dass es allgemein um Programmiersprachen gehen soll.

            Dass in PHP sogar assoziative Arrays sortiert sind, stellt lediglich eine besondere Implementierung unter PHP dar - eine generelle Forderung dieser Art gibt es für assoziative Arrays, soweit ich weiß, aber nicht.

            Das Problem rührt daher, dass "assoziatives Array" ein Bezeichner für etwas ist, was man in vielen Programmiersprachen irgendwie vorfindet, was sich aber im Detail höchst unterschiedlich verhält. Insofern würde ich eben gerade NICHT davon sprechen, dass die Eigenschaft "ist immer unsortiert" untrennbar mit "assoziatives Array" zusammengehört.

            "Array" ist eine Datenstruktur, auf die man unter Nennung eines gemeinsamen Variablenbezeichners und zusätzlich eines numerischen Indexwertes auf mehrere gleichartige Datenspeicher zugreifen kann.

            "assoziatives Array" erweitert diese Zugriffsmöglichkeit um den Aspekt, dass der Indexwert auch ein String sein kann.

            Der Wikipedia-Artikel ist in diesem Zusammenhang leider extrem verbesserungswürdig, wie die Diskussionsseite beweist.

            Alles, was darüber hinaus geht, also beispielsweise Annahmen über die Struktur oder Gleichartigkeit der Datenspeicher, über die Sortierung, das Verhalten beim Hinzufügen, mengenmäßige Begrenzungen während der Benutzung, Notwendigkeiten der initialen Größenbestimmung, Workarounds für die nachträgliche Größenerweiterung etc. sind komplett implementierungsabhängig von der jeweiligen Programmiersprache.

            Ich persönlich habe in meinem Leben schon diverse Programmiersprachen kennengelernt, und ich kann eben gerade NICHT behaupten, dass ein "Array" in allen Sprachen das gleiche ist und sich gleich verhält, geschweige denn ein "assoziatives Array".

            - Sven Rautenberg

            1. Hello,

              "Array" ist eine Datenstruktur, auf die man unter Nennung eines gemeinsamen Variablenbezeichners und zusätzlich eines numerischen Indexwertes auf mehrere gleichartige Datenspeicher zugreifen kann.

              "assoziatives Array" erweitert diese Zugriffsmöglichkeit um den Aspekt, dass der Indexwert auch ein String sein kann.

              Dann ist der String aber kein Index in die Datenstruktur mehr, sondern ein Key und das ist NICHT Dasselbe!

              Bei einem Index lässt sich unter Zugrundelegung des Datentyps und der Anfangsadresse des Arrays genau der Speicherort des gesuchten Elementes _errechnen_.

              Indexe von Arrays sind stets ordinal und haben daher auch keine Lücken.

              Ich weiß, Du wirst gleich wieder widersprechen, aber es wäre doch hilfreich, grundlegende Definitionen von Begriffen in der Datentechnik nicht zu verwässern.

              Über einen Index können Daten _geholt_ werden
              Über einen Key können Daten _gesucht_ werden.

              Liebe Grüße aus Syburg bei Dortmund

              Tom vom Berg

              --
              Nur selber lernen macht schlau
              http://bergpost.annerschbarrich.de
    2. Moin!

      also assoziativen Arrays spricht man allgemein (d.h. datenstrukturtechnisch) keine Reihnfolge zu. Deswegen sollte man sich in PHP auch nicht auf die Reihnfolge verlassen.

      Diese Aussage ist falsch. Arrays sind in PHP immer sortiert und haben eine definierte Reihenfolge, die man bei foreach feststellen und z.B. mit print_r oder var_dump sichtbar machen kann.

      In anderen Sprachen, z.B. Perl, ist das anders - aber da PHP nicht Perl ist, interessiert das nicht.

      Dass PHP-Arrays sortiert sind, ist eine der großen Stärken dieser Datenstruktur im Vergleich zu anderen Programmiersprachen.

      In PHP kann es natürlich anders gelöst sein, dies hätte aber Geschwindigkeitsnachteile.

      PHP nutzt sicherlich zum Zugriff via Index auch Hashtables, aber zusätzlich sind Zeiger implementiert, die auf das vorhergehende/nächste Element zeigen und z.B. auch mit den Funktionen reset(), next(), prev() oder each() genutzt werden können.

      - Sven Rautenberg

      1. Hallo,

        also assoziativen Arrays spricht man allgemein (d.h. datenstrukturtechnisch) keine Reihnfolge zu. Deswegen sollte man sich in PHP auch nicht auf die Reihnfolge verlassen.

        Diese Aussage ist falsch. Arrays sind in PHP immer sortiert und haben eine definierte Reihenfolge, die man bei foreach feststellen und z.B. mit print_r oder var_dump sichtbar machen kann.

        Schön und gut, aber wie ist die Ordnung? Nach Zeit des Eintragens? Alphabetische Ordnung der Keys?

        Sicher hat eine Hashtable auch eine Ordnung, wenn ich das zugrundeliegende Array einfach durchiteriere. Sofern keine Kollisionen auftreten und meine Hashfunktion keine Zufallskomponente enthält, wäre die Ordnung sogar eindeutig.

        Dem Thread steller ging es auch darum, _wie_ das geordnet ist. Und darüber hat sich bisher noch keiner geäußert.

        Wenn die Ordnung von der Hashfunktion abhängt, dann bringt einem dies relativ wenig.

        Nach ersten Tests scheint die Ordnung von der Reihnfolge des Eintragens/Erstellens abzuhängen (dafür würde auch die Listenfunktionen (prev, next) von PHP sprechen), verlassen würde ich mich aber nicht unbedingt darauf (und eben dies sagte ich). Außerdem sollte bei assoziativen Arrays die Ordnung/Position nicht unbedingt eine Rolle spielen, da dies etwas gegen das Konzept von assoziativen Arrays bzw. Hashmaps/Hashtables spricht. Für soetwas wären andere Datenstrukturen empfehlenswerter (leider ist PHP recht schlecht in der Unterstüzung dieser).

        Grüße
        Klaus

        1. Hello,

          Dem Thread steller ging es auch darum, _wie_ das geordnet ist. Und darüber hat sich bisher noch keiner geäußert.

          Neue Einträge werden dort eingefügt, wo Du es verlangst:
             vor dem Ende Kette, also hinter dem letzten Element der Kette:
             http://www.php.net/manual/en/function.array-push.php
          oder
             vor dem ersten Element, also nach dem Anfang der kette
             http://www.php.net/manual/en/function.array-unshift.php

          Und wenn Du den Index-Operator ($_array[]=$neues_element) benutzt, der ja eigentlich ein Key-Operator ist (*gg*), dann wird das Element auch am Ende eingefügt.

          Wie es in der internen Speicherstruktur geregelt wird, geht uns nichts an.

          Liebe Grüße aus Syburg bei Dortmund

          Tom vom Berg

          --
          Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de
          1. Hallo,

            Und wenn Du den Index-Operator ($_array[]=$neues_element) benutzt, der ja eigentlich ein Key-Operator ist (*gg*), dann wird das Element auch am Ende eingefügt.

            und was ist, wenn ich $array['neuer_key'] = 123; schreibe, und das Element mit dem Key 'neuer_key' noch nicht vorhanden ist?
            Wo taucht dieses in der Reihnfolge auf.

            (Persönlich würde ich es am Ende vermuten).

            Wie es in der internen Speicherstruktur geregelt wird, geht uns nichts an.

            Da geb ich dir recht. Ist nur die Frage, ob es nach außen eine eindeutige, zuverlässige und nachvollziehbare Ordnung gibt, wenn ich beispielsweise $array['neuer_key'] = 123; schreibe?

            Grüße
            Klaus

            1. Hello,

              Wie es in der internen Speicherstruktur geregelt wird, geht uns nichts an.
              Da geb ich dir recht. Ist nur die Frage, ob es nach außen eine eindeutige, zuverlässige und nachvollziehbare Ordnung gibt, wenn ich beispielsweise $array['neuer_key'] = 123; schreibe?

              Als erstes hilft Dir vielleicht dieses kleine Testscript:

              <?php   ### insert_key.php ###

              wo wird ein neues Arrayelement eingefügt?

              #------------------------------------------------
              function display(&$_liste)
              {
                  echo "<pre>\r\n";
                  echo htmlspecialchars(print_r($_liste,1));
                  echo "</pre>\r\n";
              }
              #------------------------------------------------
              function display_types(&$_liste)
              {
                  echo "<pre>\r\n";

              foreach($_liste as $key => $value)
                  {
                      echo htmlspecialchars($key).": ".gettype($key)."\r\n";
                  }

              echo "</pre>\r\n";
              }
              #------------------------------------------------

              $_liste = array();

              $_liste[] = 9;
              $_liste[] = 1;
              $_liste[] = '01';

              display($_liste);

              $_liste[1] = 'neuer Datensatz';

              display($_liste);

              $_liste['ende'] = "Ende im Gelände";
              $_liste['anfang'] = "Das ist der Anfang";
              $_liste['2'] = "Element '2'";

              display($_liste);

              $_liste[] = "automatisch hinzu";
              $_liste['02'] = "Extra Key '02'";
              $_liste['7'] = "Key '7'";
              $_liste[5] = "Key 5";

              display($_liste);
              display_types($_liste);

              ?>

              Und so funktioniert es:
              PHP prüft, ob ein Key übergeben wurde.

              Wenn keiner übergeben wurde:
              stellt es den größten bisher vorhandenen positiven numerischen Key fest, addiert eins und fügt das Element am Ende der Liste ein. Ist der größte numerische Key negativ, wird als nächster "Autokey" 0 verwendet.

              Wurde ein Key übergeben:
              dieser wird erst nach bestimmten Regeln behandelt: Literale, die Nummern darstellen, werden in ihre numerischen Äquivalente umgewandelt, wenn sie nicht mit einer führenden Null geschreieben werden.
              Alphanumerische Keys werden nicht angetastet.
              Dann wird die Liste (also bei verzweigten Arrays nur der aktuelle Zweig des Baumes) iteriert und nach dem effektiven Schlüssel gesucht. Ist dieser vorhanden, wird das Element ersetzt, ist dieser nicht vorhanden, wird das Element am Ende eingefügt.

              Das ist verbrieftes Verhalten von PHP.

              Nachvollziehen kann man das in den Sourcen, die ich mir nun auch nochmal herauskramen werde.

              Liebe Grüße aus Syburg bei Dortmund

              Tom vom Berg

              --
              Nur selber lernen macht schlau
              http://bergpost.annerschbarrich.de