String in mehrdimensionales Array splitten
Gunther
- php
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
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.
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]=Text4diese 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
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.
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
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.