如何将字符串分解为多级数组?

I was wondering if it's possible to do something like this.

I'm having the following string:

Parent1@MiddleA%Child|Child|Child|MiddleB%Child|Child|Child|Parent2@MiddleA%|Child

And I'd like to explode it into something like:

-Parent1
---MiddleA
------Child
------Child
------Child
---MiddleB
------Child
------Child
------Child
-Parent2
---MiddleA
------Child

I don't understand how to explode it and then explode it again to create an output like above.

The idea is that every parent will be identified with a trailing @, every child of that parent will have a trailing % and every child of that child will have a trailing|.

The data you give as input in your question:

Parent1@MiddleA%Child|Child|Child|MiddleB%Child|Child|Child|Parent2@MiddleA%|Child

is not really well fitting to produce the output you ask for. It's even syntactically incorrect at it's end, the delimiters in MiddleA%|Child specifically.

Correnting this, you can easily do it with preg_split:

$str = 'Parent1@MiddleA%Child|Child|Child|MiddleB%Child|Child|Child|Parent2@MiddleA%Child|';

$elements = preg_split('~([^@%|]+?[@%|])~', $str, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);

$types = '@%|';
foreach($elements as $element)
{
    $label = substr($element, 0, -1);
    $type = substr($element, -1);
    $indentValue = strpos($types, $type);
    if (FALSE === $indentValue) throw new Exception('Invalid string given.');
    $indent = str_repeat('-', $indentValue * 2 + 1);
    printf("%s %s
", $indent, $label);
}

If you don't have the input string in a valid format, you need to fix it first, e.g. with an appropriate parser or you need to react on the bogus cases inside the foreach loop.

Edit: This is an modified example that turns the string into a tree-like structure so you can output it with nested foreach loops:

$str = 'Parent1@MiddleA%Child|Child|Child|MiddleB%Child|Child|Child|Parent2@MiddleA%Child|';

$types = '@%|';
$pattern = sprintf('~([^%1$s]+?[%1$s])~', $types);
$elements = preg_split($pattern, $str, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);

$tree = array();
foreach($elements as $element)
{
    $label = substr($element, 0, -1);
    $type = substr($element, -1);
    $indentValue = strpos($types, $type);
    if (FALSE === $indentValue) throw new Exception('Invalid string given.');

    $add =& $tree;
    for($i = $indentValue; $i--;)
    {
        $index = max(0, count($add)-1);
        $add =& $add[$index][1];
    }
    $add[] = array($label, array());
    unset($add);
}

foreach($tree as $level1)
{
    echo '<div>', $level1[0], "
";
    foreach($level1[1] as $level2)
    {
        echo '  <h3>', $level2[0], '</h3>', "
";
        foreach($level2[1] as $level3)
        {
            echo '    <span>', $level3[0],'</span>', "
";
        }
    }
    echo '</div>', "
";
}

(Demo) - Hope this is helpful.

I guess there's no way to automatically explode it to multi-dimension array, so you have to write your specific algorythm to do the job. There is a logical sequence in the string so it can easilly be transformed. Start with exploding by "@", then for each element explode by "A%", and then by "|".

<?php
$string = "Parent1@MiddleA%Child|Child|Child|MiddleB%Child|Child|Child|Parent2@MiddleA%|Child";

$explode1 = explode ("@",$string);

foreach ($explode1 as $str)
{

  $explode2 = explode("|", $str);

  foreach ($explode2 as $str2)
  {
    $explode3 = explode ("%", $str2);

        foreach($explode3 as $str3)
        {
        echo ($str3 != "") ? $str3 . "<br/>" : "";
        }
  }

}
?>

will output:

Parent1
MiddleA
Child
Child
Child
MiddleB
Child
Child
Child
Parent2
MiddleA
Child