2

Another recursion question.

What I've tried to develop for the past few hours is a function that will let me generate a flat array of the same pages, but with the children having an identifier in front of them, (i.e. "— Sub Page, — — Sub Sub Page, etc").

I have a hierarchical array of pages, with each child page nested inside of their parent page. Here's an example of their output:

Array
(
    [0] => Array
        (
            [id] => 1
            [parent_id] => 0
            [title] => Parent Page
            [children] => Array
                (
                    [0] => Array
                        (
                            [id] => 12
                            [parent_id] => 1
                            [title] => Another Sub Page
                        )

                    [1] => Array
                        (
                            [id] => 3
                            [parent_id] => 1
                            [title] => Sub Page
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => 7
                                            [parent_id] => 3
                                            [title] => Sub Sub Page
                                        )

                                )

                        )

                )

        )

    [1] => Array
        (
            [id] => 8
            [parent_id] => 0
            [title] => Another Parent Page
        )

)

I've been able to get it working until I reach the second level of the recursion and then it's still generating only one —. I want to make the solution recursive.

What I'm looking for in the final output using the example above is:

Array
(
    [1] => Parent Page
    [12] => — Another Sub Page
    [3] => — Sub Page
    [7] => — — Sub Sub Page
    [8] => Another Parent Page
)
3
  • 1
    Where's the code for your solution? Commented Dec 22, 2011 at 22:54
  • Hey Tim, I've ran through possibly hundreds of iterations trying to come up with the correct solutions. That is to say, I haven't been keeping all of my attempts to share. If you would like me to come up with that solution again, I can. Commented Dec 22, 2011 at 22:57
  • you should provide var_export() output for questions like this. Commented Dec 22, 2011 at 23:36

3 Answers 3

2
function generate_array(array $arr, &$output = array(), $index = 0)
{
    foreach($arr as $item)
    {
        $output[$item['id']] = str_repeat('— ', $index) . $item['title'];
        if(isset($item['children']))
        {
            generate_array($item['children'], $output, $index + 1);
        }
    }
    return $output;
}

$output = generate_array($arr);

The data stored in $output would be:

Array
(
    [1] =>  Parent Page
    [12] => — Another Sub Page
    [3] => — Sub Page
    [7] => — — Sub Sub Page
    [8] =>  Another Parent Page
)
Sign up to request clarification or add additional context in comments.

1 Comment

+1 You got there first. I deleted my answer to avoid dilution, since it was remarkably similar.
2
<?php
$output = array();
$iter = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach ($iter as $key => $val) {
    if ($key === 'title') {
        $output[] = str_repeat('&mdash;', floor($iter->getDepth()/2)) . $val;
    }
}
print_r($output);

You could also do iterative

$stack = $output = array();
$stack[] = array(0, $array);
while ($stack) {
    list($depth, $nodes) = array_pop($stack);
    foreach ($nodes as $node) {
        if (isset($node['children'])) {
            $stack[] = array($depth + 1, $node['children']);
        }
        $output[] = str_repeat('&mdash;', $depth) . $node['title'];
    }
}
print_r($output);

It's worth mentioning that despite their name, the RecursiveIterator's don't actually use recursion internally. They manage a stack similar to my second example.

Comments

1

I used a sample array like this:

$array = array(
    array(
        'title' => 'Test',
        'children' => array(
            array(
                'title' => 'test child',
                'children' => array(
                    array(
                        'title' => 'yo dawg, i heard you like recursion!'
                    )
                )
            )
        )
    ),
    array(
        'title' => 'Test 2',
        'children' => array()
    )
);

and the function is this:

function flatIt($array, $depth = 0, &$flat = array())
{    
    foreach ($array as $item) {
        $flat[] = array('title' => str_repeat('&mdash;', $depth) . $item['title']);

        if (!empty ($item['children'])) {
            flatIt($item['children'], $depth + 1, $flat);
        }
    }

    return $flat;
}

When you call the function like this:

$result = flatIt($array);
var_dump($result);

You will get these results:

array
  0 => 
    array
      'title' => string 'Test' (length=4)
  1 => 
    array
      'title' => string '&mdash;test child' (length=17)
  2 => 
    array
      'title' => string '&mdash;&mdash;yo dawg, i heard you like recursion!' (length=50)
  3 => 
    array
      'title' => string 'Test 2' (length=6)

1 Comment

By the way, i did it with recursion but i hope someone will come up with a "iterative" approach.

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.