Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Werte an multidimensionales Array anhängen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] Werte an multidimensionales Array anhängen

    Beispiel, ich habe folgende Datenstruktur:
    PHP-Code:
    $data = array(
                
    => array('a''b''c'),
                
    => array('d''e''f' => array('g''h''i')),
                
    => array('j''k''l')
                ); 
    Dazu habe ich einen Pfad in das Array:
    PHP-Code:
    $path = array(2'f'); 
    Und hänge nun neue Daten an der via $path angegebenen Position ein:
    PHP-Code:
    $virtualArray '';
    foreach(
    $path as $curKey)
    {
        
    $virtualArray .= '[\'' $curKey '\']';
    }
    eval(
    '$data' $virtualArray '[\'m\'] = array(\'x\', \'y\', \'z\');'); 
    Das funktioniert so und ergibt:
    PHP-Code:
    $data = array(
                
    => array('a''b''c'),
                
    => array('d''e''f' => array('g''h''i''m' => array('x''y''z'))),
                
    => array('j''k''l')
                ); 
    Zwar kommen alle Daten aus einer DB, nur kommt der Weg über eval() (habe ich irgendwo so abgekupfert) trotzdem ein wenig befremdlich vor. Hat jemand noch eine gute Idee wie ich sonst schreibend auf eine beliebige Stelle in einem (bestehenden) multidimensionalen Array zugreifen kann, ohne eval() und ohne die Verschachtelungstiefe oder die Keys fest einzuprogrammieren?




    P.S. $path wird dynamisch aus einem gegebenen Key erzeugt:
    PHP-Code:
    /**
     * recursive search for key in a multidimensional array and return path as array
     * based on http://www.sitepoint.com/forums/showthread.php?p=4553691#post4553691
     * inserted "array_pop($stack); continue;" to switch back from deeper to lower levels, if key not yet found
     * 
     * @license Do-whatever-you-want-to-do-with-this-code-License
     * @param array heystack multidimensional array to search in
     * @param string needle key to be found
     * @param array stack current path
     * @return array path to key or false if not found
     */
    function arrayKeyPath($heystack$needle$stack = array())
    {
        if(
    is_array($heystack))
        {
            foreach(
    $heystack as $k => $v)
            {
                if(
    $k == $needle)
                {
                    
    array_push($stack$k);
                    return 
    $stack;
                }
                if(
    is_array($v))
                {
                    
    array_push($stack$k);
                    
    $out arrayKeyPath($v$needle$stack);
                    if(
    $out == false)
                    {
                        
    array_pop($stack);
                        continue;
                    }
                    else
                    {
                        return 
    $out;
                    }
                }
            }
            return 
    false;
        }
        else
        {
            return 
    false;
        }

    Je grösser der Dachschaden, desto schöner der Ausblick zum Himmel. - [WIKI]Karlheinz Deschner[/WIKI]

  • #2
    Ach ja, daran habe ich mich auch mehrfach dran probiert (für ein Request-Parameter-Objekt). Letztendlich habe ich das dann nie benutzt, weil es eben doch anders ist, mit echten Arrays zu arbeiten.
    [COLOR="#F5F5FF"]--[/COLOR]
    [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
    [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
    [COLOR="#F5F5FF"]
    --[/COLOR]

    Kommentar


    • #3
      Zitat von nikosch Beitrag anzeigen
      Letztendlich habe ich das dann nie benutzt, weil es eben doch anders ist, mit echten Arrays zu arbeiten.
      Wie meinen? Den oben dargestellten Weg nutze ich z.Z. um ein Array mit verschachtelten Kommentaren zu füllen, welches an zwei Stellen (unter Nutzung zweier verschiedener Templates) rekursiv ausgelesen wird.
      Je grösser der Dachschaden, desto schöner der Ausblick zum Himmel. - [WIKI]Karlheinz Deschner[/WIKI]

      Kommentar


      • #4
        Kann mir da zwar jetzt nichts drunter vorstellen, aber vielleicht wären Objekte für Dich ein Weg.
        [COLOR="#F5F5FF"]--[/COLOR]
        [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
        „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
        [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
        [COLOR="#F5F5FF"]
        --[/COLOR]

        Kommentar


        • #5
          Zitat von feeela Beitrag anzeigen
          Hat jemand noch eine gute Idee wie ich sonst schreibend auf eine beliebige Stelle in einem (bestehenden) multidimensionalen Array zugreifen kann, ohne eval() und ohne die Verschachtelungstiefe oder die Keys fest einzuprogrammieren
          Moin, habe die Frage nicht ganz verstanden.

          Mit deinem gegebenen Pfad sähe ein statischer Zugriff für mich so aus:
          PHP-Code:
          $data[2]['f'] = 'zuzuweisender wert'
          Aber dein Beispiel macht aus
          2 => array('d', 'e', 'f' => array('g', 'h', 'i')),
          dieses
          2 => array('d', 'e', 'f' => array('g', 'h', 'i', 'm' => array('x', 'y', 'z'))),
          Vielleicht verlierst du dazu noch ein paar Worte.

          Kommentar


          • #6
            Ebenso wie hpf kann ich deine Beispieldaten und das (angeblich) korrekte Ergebnis nicht nachvollziehen.

            Zitat von feeela Beitrag anzeigen
            Das funktioniert so und ergibt:
            PHP-Code:
            $data = array(
                        
            => array('a''b''c'),
                        
            => array('d''e''f' => array('g''h''i''m' => array('x''y''z'))),
                        
            => array('j''k''l')
                        ); 
            Auch in Bezug hierauf verstehe ich „funktioniert so“ nicht ganz, weil aus dem Eintrag, der ursprünglich unter dem Key 3 vorhanden war, jetzt plötzlich einer mit dem Key 4 geworden ist ...?

            Hat jemand noch eine gute Idee wie ich sonst schreibend auf eine beliebige Stelle in einem (bestehenden) multidimensionalen Array zugreifen kann, ohne eval() und ohne die Verschachtelungstiefe oder die Keys fest einzuprogrammieren?
            Mit Referenzen arbeiten, und dabei von einer Ebene zur nächsten wechseln:

            PHP-Code:
            $data = array( 
                        
            => array('a''b''c'), 
                        
            => array('d''e''f' => array('g''h''i')), 
                        
            => array('j''k''l'
                        ); 

            $path = array(2'f'); 

            $pos = &$data;

            foreach(
            $path as $index) {
              if(isset(
            $pos[$index])) {
                
            $pos = &$pos[$index];
              }
              else {
                echo 
            'Fehler, angegebener Pfad existiert im Array nicht.';
                break;
              }
            }

            $pos = array('x''y''z');

            print_r($data); 
            Das ergibt dann anschliessend folgendes:
            Code:
            Array
            (
                [1] => Array
                    (
                        [0] => a
                        [1] => b
                        [2] => c
                    )
            
                [2] => Array
                    (
                        [0] => d
                        [1] => e
                        [f] => Array
                            (
                                [0] => x
                                [1] => y
                                [2] => z
                            )
            
                    )
            
                [3] => Array
                    (
                        [0] => j
                        [1] => k
                        [2] => l
                    )
            
            )
            Wie auch hpf ist dass das einzige, was ich mir hier überhaupt als sinnvolles Ergebnis vorstellen kann, wenn man so wie von dir beschrieben vorgehen will.
            Deine Beispieldaten passen nicht wirklich zur Beschreibung dessen, was du vorhast - oder dem, was wir verstanden haben.


            Und die Fehlerbehandlung in meinem Beispiel muss natürlich noch ausgebaut werden, bzw. passender darauf reagiert werden. Denn andernfalls werden die neuen Daten, wenn der angegebene „Pfad“ im Array nicht existiert, irgendwo hin geschrieben (und dabei ggf. bestehende Daten überschrieben).
            In dem Falle wäre es natürlich denkbar, „fehlende“ Array-Ebenen mit dem angegebenen Key erst mal zu erstellen.
            [SIZE="1"]RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?[/SIZE]

            Kommentar


            • #7
              Danke erst einmal für die Antworten. Scheinbar ist das an den Beispieldaten doch ein wenig schwer nachzuvollziehen.

              Ziel der Geschichte war/ist einen Kommentarbaum in MySQL abzubilden und diesen dann in ein Array zu laden. Da MySQL selbst keine rekursiven SELECTs unterstützt, muss also eine Funktion her, welche aus der eindimensionalen Tabelle wieder einen Tree zusammensetzt. Laut eigener Recherche wäre eine gute Alternative die Verwendung von Nested Sets um in MySQL einen Baum abzubilden, ich wollte es gerne aber mit einer Tabllen-Struktur wie folgend versuchen: (auch dies wieder vereinfacht)
              Code:
              Tabelle comments:
              - `comment_id`
              - `parent_comment_id`
              - `content`
              Aus einem Ergebnis einer DB-Abfrage:
              Code:
              ResultSet
              (
              	array('comment_id' => 1, 'parent_comment_id' => null, 'content' => 'Bla1')
              	array('comment_id' => 2, 'parent_comment_id' => null, 'content' => 'Bla2')
              	array('comment_id' => 3, 'parent_comment_id' => 2, 'content' => 'Bla3')
              	array('comment_id' => 4, 'parent_comment_id' => 3, 'content' => 'Bla4')
              	array('comment_id' => 5, 'parent_comment_id' => null, 'content' => 'Bla5')
              )
              sollte dann eben ein beliebig tief verschachteltes Array entstehen...
              (wobei der Eintrag 'child_comments' optional ist)
              Code:
              Comments
              (
              	array('comment_id' => 1, 'parent_comment_id' => null, 'content' => 'Bla1'),
              	array('comment_id' => 2, 'parent_comment_id' => null, 'content' => 'Bla2', 'child_comments' => array(
              		array('comment_id' => 3, 'parent_comment_id' => 2, 'content' => 'Bla3', 'child_comments' => array(
              		    array('comment_id' => 4, 'parent_comment_id' => 3, 'content' => 'Bla4')
              			)
              		)
              	)
              	array('comment_id' => 5, 'parent_comment_id' => null, 'content' => 'Bla5')
              )
              Hier der momentan verwendete Code als Auszug aus der umgebenen Klasse, daher nicht lauffähig. arrayKeyPath() wie im ersten Post. (Ja, ich weiß - auch die Kommentare sollten konsequenterweise Objekte sein...)
              Hier der komplette Beispielcode vom ersten Post.



              @hpf
              Ein statischer Zugriff wie von dir gepostet, würde die bestehenden Daten überschreiben, es soll jedoch angehängt werden. (daher eine neue Ebene im eval)
              PHP-Code:
              $data[2]['f'] = 'zuzuweisender wert';
              /* würde array('g', 'h', 'i') überschreiben */
              => array('d''e''f' => array('g''h''i')), 
              @ChrisB
              Zitat von ChrisB Beitrag anzeigen
              [...] aus dem Eintrag, der ursprünglich unter dem Key 3 vorhanden war, jetzt plötzlich einer mit dem Key 4 geworden ist ...?
              Mein Fehler: ich hatte den Code eingefügt, aber die Ausgabe von print_r abgetippt. Ich habs oben korrigiert.

              Zitat von ChrisB Beitrag anzeigen
              Mit Referenzen arbeiten, und dabei von einer Ebene zur nächsten wechseln:
              Die Lösung gefällt mir, ich werde das mal im nüchternen Zustand ausprobieren. Dies scheint mir eine gute Antwort auf meine Frage zu sein. Alternativ müsste ich wohl auch hierfür eine rekursive Funktion bauen. Ansonsten siehe @hpf.

              Zitat von ChrisB Beitrag anzeigen
              Fehlerbehandlung [...] Denn andernfalls werden die neuen Daten, wenn der angegebene „Pfad“ im Array nicht existiert, irgendwo hin geschrieben [...]. In dem Falle wäre es natürlich denkbar, „fehlende“ Array-Ebenen mit dem angegebenen Key erst mal zu erstellen.
              Ich denke drüber nach, aber da der Pfad aus dem bestehenden Array ermittelt wird, sollte es da kaum Probleme geben.


              Danke,

              Feeela
              Je grösser der Dachschaden, desto schöner der Ausblick zum Himmel. - [WIKI]Karlheinz Deschner[/WIKI]

              Kommentar

              Lädt...
              X