Gunther: Multidimensionales Array aus exploded String erstellen

Hallo werte Selfgemeinde,

ich bräuchte biite mal Hilfe, bzw. eine Idee, wie ich folgendes umsetzen kann:
Und zwar habe ich in einem Array mehrere Keys, die die Form "abc", "abc/def" oder "abc/def/.../xyz" haben.

Nun möchte ich jeweils aus diesen Keys, sofern sie die Form "abc/def/.../xyz" haben, ein multidimensionales Array erstellen, bei dem die Teile "abc", "def" usw. jeweils einen Array Schlüssel bilden und der letzte Teil ("xyz") den Wert.

Dazu zerlege ich den Key per explode() und iteriere über das so neu gewonnene Array.

Mein Problem besteht aber nun darin, dass ich keine Idee habe, wie ich jetzt mein multidimensionales Array erstellen soll?

Wichtig ist natürlich auch, dass entsprechende Schlüssel (Level) nur eingefügt werden, wenn sie noch nicht existieren. Andernfalls soll lediglich der Wert eingefügt werden.

Puh, gar nicht so einfach, mein Vorhaben verständlich zu formulieren. Ich hoffe, ihr versteht mich und mein Anliegen dennoch.

Für Tipps/ Ideen meinen besten Dank im Voraus!

Gruß Gunther

  1. Moin

    Das riecht stark nach Rekursion in Verbindung mit Call by Reference ;)

    Gruß Bobby

    --
    -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
    ### Henry L. Mencken ###
    -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
    ### Viktor Frankl ###
    ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
    1. Hello,

      Das riecht stark nach Rekursion in Verbindung mit Call by Reference ;)

      Ich begrüße Dich im Club.
      Für die Umwanflung des Arrays in eine URL-Struktur ist das vermutlich unumgänglich. Ich habe das hier schan mal vorgestellt.

      Für den Rückweg könnte man mMn vermutlich mit foreach() in Schachtelung und isset() zum Erfolg kommen.

      Das wesentliche wird sein, dass man bei der ersten Umwandlung (Zeilen in Arrays) nicht aus versehen einen Zielwert ungleich NULL oder FALSE angibt. Dann lässt der sich nämlich nicht mehr mehrstufig überschreiben.

      aus

      $_myList['first'] -> 'black';

      kann man direkt nicht mehr machen

      $_myList['first']['background']['value'] -> 'black';

      da $_myList['first'] breits vom Typ String ist und damit nicht implizit überschreibbar.

      Wenn $_myList['first'] allerdings auf false oder NULL zeigt, dann lässt PHP die Typüberschreibung zu Array zu.

      Soviel nur dazu, was zu beachten ist.

      Bei der Expansion benötigt man keine Referenzen, bei der Implosuin schon.

      Die Expansion funktimniert verlustfrei, die Implosion ist an Regeln gebunden, bzw. funktioniert nicht verlustfrei!

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
       ☻_
      /▌
      / \ Nur selber lernen macht schlau
      http://bikers-lodge.com
      1. Moin!

        aus

        $_myList['first'] -> 'black';

        kann man direkt nicht mehr machen

        $_myList['first']['background']['value'] -> 'black';

        da $_myList['first'] breits vom Typ String ist und damit nicht implizit überschreibbar.

        Wenn $_myList['first'] allerdings auf false oder NULL zeigt, dann lässt PHP die Typüberschreibung zu Array zu.

        Man kann auch direkt ein leeres Array zuweisen.

        Das Problem ist aber ein anderes:

        "abc/def" ist der Key "abc" mit Value "def".

        "abc/def/ghi" ist ['abc']['def'] als Key-Kette - aber ['abc'] ist kein vorher leeres Array, sondern der Value "def".

        Die Frage ist also: Wie ist so ein Fall definiert?

        Das Problem geht übrigens nicht weg, wenn man den eigentlichen Value im String anders abspaltet:

        "abc = 1"
        "abc/def = 2"

        Hat dasselbe Problem: "abc" kann nicht gleichzeitig den Value 1 enthalten, und parallel das Array mit Key "def" sein. Da kommt man nur raus, wenn man in seinem Array mindestens noch einen Key "value" anlegt (und ausschließt, dass man selbst den Key "value" verwendet):

        ['abc']['value'] = 1
        ['abc']['def'] = array(...)

        - Sven Rautenberg

        1. Hello Sven,

          $_myList['first'] -> 'black';

          kann man direkt nicht mehr machen

          $_myList['first']['background']['value'] -> 'black';

          da $_myList['first'] breits vom Typ String ist und damit nicht implizit überschreibbar.

          Wenn $_myList['first'] allerdings auf false oder NULL zeigt, dann lässt PHP die Typüberschreibung zu Array zu.

          Man kann auch direkt ein leeres Array zuweisen.

          Das Problem ist aber ein anderes:

          "abc/def" ist der Key "abc" mit Value "def".

          "abc/def/ghi" ist ['abc']['def'] als Key-Kette - aber ['abc'] ist kein vorher leeres Array, sondern der Value "def".

          Die Frage ist also: Wie ist so ein Fall definiert?

          Das Problem geht übrigens nicht weg, wenn man den eigentlichen Value im String anders abspaltet:

          "abc = 1"
          "abc/def = 2"

          Hat dasselbe Problem: "abc" kann nicht gleichzeitig den Value 1 enthalten, und parallel das Array mit Key "def" sein. Da kommt man nur raus, wenn man in seinem Array mindestens noch einen Key "value" anlegt (und ausschließt, dass man selbst den Key "value" verwendet):

          ['abc']['value'] = 1
          ['abc']['def'] = array(...)

          ... oder die Elemente müssen eben selber auch einen Typ haben, den _wir_ hier aber nicht sehen können. So funktioniert das ja in rekursiven Verzeichnisschemata

          Da haben die Elemente entweder den Typ 'data' (oder 'file', ...), oder sie sind vom Typ 'dir', oder, oder, ...

          Das ist dann Definitionssache, welche davon dann auch nebeneinander existieren dürfen

          F /var/www/web
          D /var/www/web/example.org

          PHP stellt diese Möglichkeit in seinen Arraystrukturen nicht zur Verfügung und verhindert effektiv, dass Fehler passieren.

          Ich denke, dass Gunther da noch ein paar Informationen nachlegen muss, wenn es zur Lösung führen soll :-)

          Liebe Grüße aus dem schönen Oberharz

          Tom vom Berg

          --
           ☻_
          /▌
          / \ Nur selber lernen macht schlau
          http://bikers-lodge.com
          1. hi,

            Ich denke, dass Gunther da noch ein paar Informationen nachlegen muss, wenn es zur Lösung führen soll :-)

            Soso, Du willst es wohl ganz genau sehen ;

              
                // recursive Method  
                // Rekonstruiere das Array  
                private function reconstruct($key, &$stub = array()){  
                    // LOOKUP durchgehen  
                    foreach($this->LOOKUP as $child_key => $parent){  
                        if($parent == $key){  
                            // childs  
                            if(isset($this->KVTAB[$child_key])){  
                                $stub[$child_key] = $this->KVTAB[$child_key];  
                            }  
                            else{  
                                // Rekursion $child_key  
                                $this->reconstruct($child_key, $stub[$child_key]);  
                            }  
                        }  
                    }  
                }  
            
            

            Horst

            1. Hello Horst,

              Ich denke, dass Gunther da noch ein paar Informationen nachlegen muss, wenn es zur Lösung führen soll :-)

              Soso, Du willst es wohl ganz genau sehen ;

              Ich befürchte, dass Du Svens und meine Einwände nicht berücksichtigt hast. Wenn ein Array-Element bereits mit einem Wert (also nicht false und nicht NULL) belegt ist, kann man diesen nicht einfach (implizit) zum Key umfunktionieren. PHP lässt keine Doppelbelegung zu.

              Man kann ihn allerdings explizit umdeklarieren:

              $_array['eins'] = 1;

              geht nicht:
              $_array['eins']['zwei'] = 2;

              geht:
              $_array['eins'] = array();
              $_array['eins']['zwei'] = 2;

              Dann ist aber der Wert 1 verloren!

              Das meinten Sven und ich sinngemäß.

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bikers-lodge.com
              1. Hello all,

                Ich denke, dass Gunther da noch ein paar Informationen nachlegen muss, wenn es zur Lösung führen soll :-)

                Soso, Du willst es wohl ganz genau sehen ;

                Ich befürchte, dass Du Svens und meine Einwände nicht berücksichtigt hast. Wenn ein Array-Element bereits mit einem Wert (also nicht false und nicht NULL) belegt ist, kann man diesen nicht einfach (implizit) zum Key umfunktionieren. PHP lässt keine Doppelbelegung zu.

                Man kann ihn allerdings explizit umdeklarieren:

                $_array['eins'] = 1;

                geht nicht:
                $_array['eins']['zwei'] = 2;

                geht:
                $_array['eins'] = array();
                $_array['eins']['zwei'] = 2;

                Dann ist aber der Wert 1 verloren!

                Das meinten Sven und ich sinngemäß.

                Genau, und deshalb verwende ich die zweite Variante. ;-)
                Der Order-Wert wird nur für die Sortierung gebraucht und interessiert anschließend (also nach der Sortierung) eigentlich nicht mehr. Aber wenn er schon mal da ist ..., bleibt er halt.

                Ich habe übrigens inzwischen auch meine "fertige" Variante gepostet.
                Ich hoffe, dass klärt die noch offenen Fragen?

                Gruß Gunther

                1. Hello,

                  Ich habe übrigens inzwischen auch meine "fertige" Variante gepostet.
                  Ich hoffe, dass klärt die noch offenen Fragen?

                  Die habe ich noch nicht durch, denn Du hast dafür leider die (verbalen) Randbedingungen noch nicht genannt und die implizite Dokumentation (also Kommentare innerhalb der Funktionen usw.) lässt ebenfalls zu Wünschen übrig.

                  Ich will Dich hier nicht ärgern. Ich glaube auch, dass Du das verstanden hast :-)

                  Es geht einfach nur um die Nachvollziehbarkeit einer Fragestellung oder eines Problems und wie das dann (vermeintlich) gelöst wurde.

                  Leider gibt es hier viel zu viele "Mediziner", die einfach nur Pillen ausschütten gegen das Symptom, anstatt danach zu fragen, woher die Krankheit stammt...

                  Liebe Grüße aus dem schönen Oberharz

                  Tom vom Berg

                  --
                   ☻_
                  /▌
                  / \ Nur selber lernen macht schlau
                  http://bikers-lodge.com
              2. hi,

                Ich befürchte, dass Du Svens und meine Einwände nicht berücksichtigt hast. Wenn ein Array-Element bereits mit einem Wert (also nicht false und nicht NULL) belegt ist, kann man diesen nicht einfach (implizit) zum Key umfunktionieren. PHP lässt keine Doppelbelegung zu.

                Ach was ;)

                Ne, Du hast Recht, Deine Einwände habe ich tatsächlich nicht berücksichtigt ;)

                Horst

    2. Moin!

      Das riecht stark nach Rekursion in Verbindung mit Call by Reference ;)

      Jep, das war's ...! ;-)
      Manchmal ist das mit dem Wald und den Bäumen echt schwer, wenn man das Brett schon vorm Kopf hat ...!

      Besten Dank, natürlich auch an alle anderen!

      Gruß Gunther

      1. Hello,

        Besten Dank, natürlich auch an alle anderen!

        Beispiel?
        Lösung?

        Das wäre das schönste Dankeschön und außerdem nochmal eine Abschlussprüfung für Dich. Du willst doch bestimmt alle möglichen Fälle erfassen? Meistens ist man selber schon mit einem erfolgreichen Spezialfall zufrieden ...

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bikers-lodge.com
        1. Hello,

          Besten Dank, natürlich auch an alle anderen!

          Beispiel?
          Lösung?

          ja kommt ..., war mir gestern nur zu spät und außerdem habe ich noch eine Sortierfunktion dazu gebaut. Ich hoffe, mir sind beim anpassen an die Demo-Version hier keine Fehler unterlaufen!?

          Im Original funktioniert es jedenfalls ...! ;-)

            
          $paths = array(  
              'abc' => array('order' => '2'),  
              'abc/abc' => array('order' => '1'),  
              'abc/def' => array('order' => '3'),  
              'abc/ghi' => array('order' => '2'),  
              'def' => array('order' => '1'),  
              'def/abc' => array('order' => '2'),  
              'def/def' => array('order' => '1'),  
              'abc/def/abc' => array('order' => '2'),  
              'abc/def/def' => array('order' => '1'),  
              'ghi' => array('order' => '3')  
          );  
            
          $meinArray = array();  
            
          foreach($paths as $index => $tmp) {  
              if($index == 'frontpage') continue;  
              $indexes = explode('/', $index);  
              $counter = count($indexes);  
              if($counter > 1) {  
                  $meinArrayReference = &$meinArray;  
                  for($i = 0; $i < ($counter - 1); $i++) {  
                      if (!array_key_exists($indexes[$i], $meinArrayReference)) {  
                          $meinArrayReference[$indexes[$i]] = array();  
                      }  
                      $meinArrayReference = &$meinArrayReference[$indexes[$i]];  
                  }  
                  $meinArrayReference[$indexes[$i]] = array('order' => $tmp['order']);  
              }  
              else {  
                  $meinArray[$indexes[0]] = array('order' => $tmp['order']);  
              }  
          }  
            
          uasort($meinArray, 'cmp');  
            
          $meinArray = sortMultiArray($meinArray);  
            
          print_r($meinArray);  
          exit;  
            
          function sortMultiArray($arr) {  
              foreach ($arr as &$subArr) {  
                  if(count($subArr) > 1) {  
                      uasort($subArr, 'cmp');  
                      sortMultiArray($subArr);  
                  }  
              }  
              return $arr;  
          }  
            
          function cmp($a, $b) {  
          	if ($a['order'] == $b['order']) {  
                  return 0;  
              }  
              return ($a['order'] < $b['order']) ? -1 : 1;  
          }  
          
          

          Macht zumindest jetzt das, was ich möchte und für die weitere Verarbeitung brauche.

          Verbesserungsvorschläge sind natürlich jederzeit willkommen - danke!

          Gruß Gunther

  2. Mahlzeit,

    würde ein einfaches array_merge() in die richtige Richtung gehen?

    --
    42
  3. Hello,

    was habe ich bisher verstanden?

    Es gibt eine Stream, den man in Strings zerlegen kann.
    Aus den Strings soll dann erstmal werden:

    "abc"                    -> $_array['abc'] -> NULL;
    "abc/def"                -> $_array['abc']['def'] -> NULL;
    "abc/def/bloedmann/xyz"  -> $_array['abc']['def']['bloedmann']['xyz'] -> NULL;

    Wird nun klar, wo erst einmal das Problem liegt?

    Wenn es keine weiteren Metadaten zu den Fragmenten gibt, muss man da vermutlich mehrstufig vorgehen. Also erstmal aus dem Stream die Strings entwicklen, dann die Strings in Arrays umwandeln (explode()), dann die Arrays aus den Zeilen in ein Gesamt-Array übertragen

    Und darauf  liegt jetzt der Fokus :-O

    Vorschläge?

    Ich habe das umgekehrte Verfahren vor langer Zeit im Archiv hinterlassen, also wie man aus einer Raumstruktur ("Mutlidimensonales Array") eine normalisierte Datstellung erzeugen kann.

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bikers-lodge.com