3

I have a multidimensional array that looks like this

[0] => Array
    (
        [recordId] => 5
        [leaf] => 1
        [children] => Array
            (
                [0] => Array
                    (
                        [recordId] => 6
                        [leaf] => 1
                        [children] => Array
                            (
                                [0] => Array
                                    (
                                        [recordId] => 7
                                        [leaf] => 1
                                    )
                            )
                    )
                [1] => Array
                    (
                        [recordId] => 8
                        [leaf] => 1
                        [children] => Array
                            (
                                [0] => Array
                                    (
                                        [recordId] => 9
                                        [leaf] => 1
                                    )
                                [1] => Array
                                    (
                                        [recordId] => 10
                                        [leaf] => 1
                                    )
                            )
                    )
            )
    )

Each node has a 'leaf' key that is TRUE by default and has a 'children' array if there are further nodes down.

I need to set the 'leaf' key value to FALSE if there is a 'children' array contained in the node. That way only final nodes have the leaf = TRUE designation.

I've tried searching but can't find code to do what I need and I can't wrap my head around the recursive function that I believe is needed.

Any ideas how I could accomplish this in PHP?

Thanks for the help.

Chris
  • 307
  • 1
  • 6
  • 14
  • Keep in mind that `1` and `true` are not the same thing. – Halcyon Jun 20 '11 at 20:10
  • Also, I would argue that 'leaf' is derived from the node not having any children, that is (in my view) the definition of a leaf (> it doesn't have any children). – Halcyon Jun 20 '11 at 20:11
  • @Frits: So an empty `children` array should mean children or not? – hakre Jun 20 '11 at 20:48

3 Answers3

3

In theory this should work:

function findChild(&$array){
     foreach($array as &$arr){
            if(isset($arr['children'])){
                  $arr['leaf'] = 0; //there are children
                  findChild($arr['children']);
            }
            else {
                  $arr['leaf'] = 1; //there are no children
            }
     }
}

Here is a working demo: http://codepad.org/AnYiRpES

Naftali
  • 144,921
  • 39
  • 244
  • 303
  • Note the use of `&` which turns the parameter into a pass-by-reference (so it modifies the original array). – Halcyon Jun 20 '11 at 20:13
  • That's exactly what I needed (well I had to reverse the 1 and 0). Thank you very much. – Chris Jun 20 '11 at 20:15
  • @Chris -- no problemo ^_^. what do u mean you had to reverse the 1 and the 0? – Naftali Jun 20 '11 at 20:17
  • never mind. ok, did not realize that leaf was supposed to be 0 if there were children ^_^ – Naftali Jun 20 '11 at 20:18
  • What you had coded would set leaf to 1(true) if it had children. I needed the opposite, if NO children, ie final node in a branch, set leaf to 1. – Chris Jun 20 '11 at 20:24
  • @Chris -- i know, i saw that after you mentioned it, i switched it around and changed the demo for ya :-D – Naftali Jun 20 '11 at 20:26
3

Pretty simple actually:

function leafOrNotLeaf(array $array) {
    foreach ($array as $key => $sub) {
        if (isset($sub['children'])) {
            $array[$key]['leaf'] = false;
            $array[$key]['children'] = leafOrNotLeaf($sub['children']);
        }
    }
    return $array;
}

$new_array = leafOrNotLeaf($array);
netcoder
  • 66,435
  • 19
  • 125
  • 142
3

Walking on the actual $array:

array_walk($array, $walker = function (&$node) use (&$walker) {
    $node['leaf'] = (int) empty($node['children'])
        OR array_walk($node['children'], $walker);
});

A bit cryptic maybe, so you gotta love PHP.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • 2
    "A bit cryptic"? Drop the "bit": it's cryptic. +1 Anyhow for creativity. ;) – netcoder Jun 20 '11 at 23:34
  • 1
    @netcoder Okay, let's drop the *bit*: `$n='array';$l='leaf';$c='children';$f=$n."_walk";$f($$n, $b=function(&$m)use(&$b,$l,$c,$f){$m[$l]=(int)empty($m[$c])OR$f($m[$c],$b);});` ;) – hakre Jun 20 '11 at 23:52