1

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|.

3
  • 1
    is there a reason for using "your own" (un-)serializing method and not the PHP "serialize" & "unserialize"? (or JSON, for that matter) Commented Oct 29, 2011 at 12:21
  • You might be able to customize a JSON parser... Commented Oct 29, 2011 at 12:21
  • i don't even know what php offers there or what json is. I'll have to do some searching. Commented Oct 29, 2011 at 14:26

3 Answers 3

0

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\n", $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], "\n";
    foreach($level1[1] as $level2)
    {
        echo '  <h3>', $level2[0], '</h3>', "\n";
        foreach($level2[1] as $level3)
        {
            echo '    <span>', $level3[0],'</span>', "\n";
        }
    }
    echo '</div>', "\n";
}

(Demo) - Hope this is helpful.

11
  • Sorry. I didn't see this. I'm not sure how to change this from giving an indent to saying if its a level 1 do this style, if level 2, do this other html. Do you get what I mean? Commented Oct 29, 2011 at 13:07
  • Wait, I think I might have it. BRB. Thank you, too. Commented Oct 29, 2011 at 13:10
  • @JackSmith: Check $indentValue, it's 0 for level 1, 1 for level 2 and so on. If it's FALSE an error occured. Commented Oct 29, 2011 at 13:11
  • I can't figure it out. I'm trying to get it so that there's a $start $value $end, with $value being the $label and $start and $end being the enclosing html. Commented Oct 29, 2011 at 13:23
  • What type of HTML do you want to output? An <ul><li><ul>... type of list? You need to tell in your question, otherwise it's not known. The output in my question was for what you've given in your question what you want to do, you need to share more in your question if you'd like me to share more in the answer. Commented Oct 29, 2011 at 13:26
0

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 "|".

0
<?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
9
  • Thank you! That makes sense. I never learnt the foreach function... how did that not occur to me?! Commented Oct 29, 2011 at 12:32
  • This looks like a flat list, I wonder this is really fitting for what OP asked for. Commented Oct 29, 2011 at 12:34
  • It's true, I can split it up if the OP wishes me to? I got the impression that he just wanted the gist of how to explode() strings... Commented Oct 29, 2011 at 12:37
  • Hmm, yeah I was trying to figure out how to also style each level. I'm experimenting now, but I'm not familiar with the function. I'm just looking at tizag, but it's not making a lot of sense to me. Commented Oct 29, 2011 at 12:43
  • Is there any flexibility in your initial string? What is that you're trying to create? Commented Oct 29, 2011 at 12:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.