Gunther: String in mehrdimensionales Array splitten

Hallo Forumsgemeinde!

Ich stehe vor folgendem Problem, das ich mir nicht zu lösen weiss.
Ich habe einen String in der Form:

Text0 *Text1 *Text2 **Text21 **Text22 ***Text221 ***Text222 *Text3 *Text4

Diesen String möchte ich nun wiefolgt in ein mehrdimensionales Array aufsplitten:

text[0]=Text0
text[1]=Text1
text[2]=Text2
text[2][1]=Text21
text[2][2]=Text22
text[2][2][1]=Text221
text[2][2][2]=Text222
text[3]=Text3
text[4]=Text4

Die Tiefe sollte dabei prinzipiell beliebig sein können.
Für Hilfe meinen besten Dank im Voraus!

Gruß Gunther

  1. Lieber Gunther,

    Text0 *Text1 *Text2 **Text21 **Text22 ***Text221 ***Text222 *Text3 *Text4

    Diesen String möchte ich nun wiefolgt in ein mehrdimensionales Array aufsplitten:

    text[0]=Text0
    text[1]=Text1
    text[2]=Text2
    text[2][1]=Text21
    text[2][2]=Text22
    text[2][2][1]=Text221
    text[2][2][2]=Text222
    text[3]=Text3
    text[4]=Text4

    diese Aufgabe ist nicht lösbar, denn wenn text[2] ein String mit "Text2" sein soll, dann kann es kein text[2][1] geben, denn das würde voraussetzen, dass text[2] ein Array ist...

    Wie sieht es denn mit folgendem Array-"Format" aus?

    $text = array (  
            [Text0] => '',  
            [Text1] => '',  
            [Text2] => array(  
                    [Text21] => '';  
                    [Text22] => array(  
                             [Text221] => '',  
                             [Text222] => ''  
                             )  
                    ),  
             [Text3] => '',  
             [Text4] => ''  
    );
    

    Liebe Grüße aus Ellwangen,

    Felix Riesterer.

    1. Hallo Felix,

      Text0 *Text1 *Text2 **Text21 **Text22 ***Text221 ***Text222 *Text3 *Text4

      Diesen String möchte ich nun wiefolgt in ein mehrdimensionales Array aufsplitten:

      text[0]=Text0
      text[1]=Text1
      text[2]=Text2
      text[2][1]=Text21
      text[2][2]=Text22
      text[2][2][1]=Text221
      text[2][2][2]=Text222
      text[3]=Text3
      text[4]=Text4

      diese Aufgabe ist nicht lösbar, denn wenn text[2] ein String mit "Text2" sein soll, dann kann es kein text[2][1] geben, denn das würde voraussetzen, dass text[2] ein Array ist...

      Ja, deshalb renne ich wahrscheinlich u.a. gedanklich immer vor die Wand.

      Wie sieht es denn mit folgendem Array-"Format" aus?

      $text = array (

      [Text0] => '',
              [Text1] => '',
              [Text2] => array(
                      [Text21] => '';
                      [Text22] => array(
                               [Text221] => '',
                               [Text222] => ''
                               )
                      ),
               [Text3] => '',
               [Text4] => ''
      );

      
      >   
        
      Hmmm, eigentlich sollten die Schlüssel ja Zahlen sein und die Werte der jeweilige Text. Und wie kriege ich den String denn erstmal überhaupt 'zerlegt'? Der obige Fall ist nur ein Beispiel. Es können theoretisch beliebig viele Punkte/ Unterpunkte sein.  
        
      Vielleicht ist mein Ansatz auch schon falsch, bzw. nicht ideal?  
      Also der Ausgangsstring hat immer dieses Format (also der Level ist quasi durch die Anzahl an Sternchen gegeben). Ziel ist es, hinterher eine hierachische Ordnung zu haben, bei der man quasi rückwärts von jedem Unterpunkt zu seinem jeweiligen übergeordneten Eintrag finden kann. Beispiel: Wenn man bei Punkt 222 ist, dann soll es quasi einen Rückwärtspfad über Punkt 22 -> Punkt 2 -> Punkt 0 geben (analog bei anderen Unterpunkten).  
        
      Ich hoffe, das ist einigermaßen verständlich, aber ich weiss nicht, wie ich es anders formulieren soll?  
        
      Gruß Gunther
      
      1. Lieber Gunther,

        Hmmm, eigentlich sollten die Schlüssel ja Zahlen sein und die Werte der jeweilige Text. Und wie kriege ich den String denn erstmal überhaupt 'zerlegt'? Der obige Fall ist nur ein Beispiel. Es können theoretisch beliebig viele Punkte/ Unterpunkte sein.

        der Vorschlag der Array-Struktur kam aus einem ganz bestimmten Anwendungsfall: Directory-Listing. Ich hatte damals diese Array-Struktur gewählt, da ich damit sehr leicht die Ordnerinhalte abbilden konnte.

        Wie kommst Du überhaupt zu Deinem String? Ich weiß gerade keine clevere Methode in aufzudröseln (will mir darüber jetzt auch gerade nicht den Kopf zerbrechen), aber vielleicht kann man ihn schon in einer wesentlich günstigeren Form generieren lassen?

        Liebe Grüße aus Ellwangen,

        Felix Riesterer.

      2. Hej,

        Und wie kriege ich den String denn erstmal überhaupt 'zerlegt'?

        Mit Rekursion. Ich kann aber kein php, daher versuch ichs mal in Pseudocode:

        Function seperateString{

        Input:  { Liste strings, int level }
          Output: { List strings }

        begin{
            /* (¹) */
            String seperator <- "\s(\*){"+level+"}(?=[^\*])"

        for( int i <- 0; i < length( strings ); i <- i + 1 ) {
              Liste splitted <- preg_split( seperator, strings[i] )
              if length( splitted ) != 1 ) {
                strings[i] <- seperateString( splitted, level + 1 )
              }
            }
          }
          end
        }

        Function seperate {

        Input: { String string }

        begin {
            List text <- new List
            text[0] <- string;
            seperateString( l, 1);
          }
        }

        ¹) Den regulären Ausdruck habe ich in Java getestet, hoffe er hilft dir trotzdem.

        text[0]=Text0
        text[1]=Text1
        text[2]=Text2
        text[2][1]=Text21
        text[2][2]=Text22
        text[2][2][1]=Text221
        text[2][2][2]=Text222
        text[3]=Text3
        text[4]=Text4

        Das Ergebnis sieht dann allerdings folgendermaßen aus:

        text[0]
        text[0][0]=Text0
        text[0][1][0]=Text1
        text[0][2][0]=Text2
        text[0][2][1]=Text21
        text[0][2][2][0]=Text22
        text[0][2][2][1]=Text221
        text[0][2][2][2]=Text222
        text[0][3]=Text3
        text[0][4]=Text4

        Das äußerste unnötige Array wirst du schon selber wieder los ;-)

        Beste Grüße
        Biesterfeld

        --
        Art.1: Et es wie et es
        Art.2: Et kütt wie et kütt
        Art.3: Et hätt noch immer jot jejange
        Das Kölsche Grundgesetz
      3. Hallo Felix und Biesterfeld,

        vielen Dank für eure nette Hilfe. :-)

        Ich habe es jetzt doch etwas anders gemacht. Das Format des Input-Strings ist so vorgegeben und kann nicht geändert werden.
        So sieht meine Zerlegung im Moment aus:

          
        preg_match_all('/\** ?[a-z|A-Z|0-9| |äöüÄÖÜß]+[^*]/', $input, $items);  
        $itemLevel = array();  
          foreach($items[0] as $k => $v) {  
           $level = substr_count ( $v, "*" , 0 );  
           $itemLevel[$k][$level] = $v;  
          }  
        
        

        Das liefert mir jetzt jeden Eintrag als Wert eines zweidimensionalen Arrays zurück, wobei der erste Schlüssel die Position innerhalb der cronologischen Reihenfolge angibt und der zweite Schlüssel den jeweiligen Level.

        Ich hoffe, dass ich jetzt damit meine gestellte Anforderung erfüllen kann. Nochmals meinen besten Dank für eure freundliche Unterstützung.

        Gruß Gunther

        PS: Das Ganze soll übrigens eine Erweiterung im neuen SELFHTML-Wiki werden.