Count number of leaves in nested array tree

2019-06-27 20:21发布

I have a nested array tree, generated from a flat array with the following function :

function convertToTree(array $flat, $idField = 'id',
                        $parentIdField = 'parentId',
                        $childNodesField = 'childNodes') {
    $indexed = array();
    // first pass - get the array indexed by the primary id  
    foreach ($flat as $row) {
        $indexed[$row[$idField]] = $row;
        $indexed[$row[$idField]][$childNodesField] = array();
    }

    //second pass  
    $root = null;
    foreach ($indexed as $id => $row) {
        $indexed[$row[$parentIdField]][$childNodesField][$id] =& $indexed[$id];
        if (!$row[$parentIdField]) {
            $root = $id;
        }

    }
    return array($root => $indexed[$root]);
}

I would need to add an entry "NUMBER OF LEAVES" for each node of my array. This entry should count ALL the leaves of all the subnodes of the node :

Array ( 
    [9] => Array ( 
        [id] => 9, 
        [parentId] => null,
        [name] => Item 0, 
        [NUMBER OF LEAVES] => 4,  (corresponding to leaves 100 and 101 + 200 and 201)
        [childNodes] => Array 
            ( 
                [1] => Array ( 
                    [id] => 1, 
                    [parentId] => 9, 
                    [name] => Item 1, 
                    [NUMBER OF LEAVES] => 2,   (corresponding to leaves 100 and 101)
                    [childNodes] => Array ( 
                        [10] => Array ( 
                            [id] => 10, 
                            [parentId] => 1, 
                            [name] => Item 10, 
                            [childNodes] => Array ( 
                                [100] => Array ( 
                                    [id] => 100, 
                                    [parentId] => 10, 
                                    [name] => Item 100, 
                                    [childNodes] => Array ( ) 
                                ) 
                                [101] => Array ( 
                                    [id] => 101, 
                                    [parentId] => 10, 
                                    [name] => Item 101, 
                                    [childNodes] => Array ( ) 
                                ) 
                            ) 
                        ) 
                    ) 
                ) 
                [2] => Array ( 
                    [id] => 2, 
                    [parentId] => 9, 
                    [name] => Item 2, 
                    [NUMBER OF LEAVES] => 2,   (corresponding to leaves 200 and 201)
                    [childNodes] => Array ( 
                        [20] => Array ( 
                            [id] => 20, 
                            [parentId] => 2, 
                            [name] => Item 20, 
                            [childNodes] => Array ( 
                                [200] => Array ( 
                                    [id] => 200, 
                                    [parentId] => 20, 
                                    [name] => Item 200, 
                                    [childNodes] => Array ( ) 
                                ) 
                                [201] => Array ( 
                                    [id] => 201, 
                                    [parentId] => 20, 
                                    [name] => Item 201, 
                                    [childNodes] => Array ( ) 
                                ) 
                            ) 
                        ) 
                    ) 
                ) 
            ) 
    ) 
)

4条回答
家丑人穷心不美
2楼-- · 2019-06-27 20:41
//find Totalaleaves
$iterator = new RecursiveIteratorIterator(
    new RecursiveArrayIterator($array),
    RecursiveIteratorIterator::SELF_FIRST
);

$ti = 0;
// NUMBER OF LEAVES keys
$tcount = 0;
// NUMBER OF LEAVES values
foreach ($iterator as $key => $item) {
    if (is_array($item) && $item['NUMBER OF LEAVES'] > 0) {
        $tcount = $tcount + $item['NUMBER OF LEAVES'];
        $ti++;
    }
}

echo "Totalleaveskeys=" . $ti;
echo "Totalleavesvalues=" . $tcount;

This solution work for the unlimited nested multidimensional arrays

查看更多
迷人小祖宗
3楼-- · 2019-06-27 20:49

The way to solve this problem is using array_walk_recursive.

Example:

new LeaveCounter();

class LeaveCounter
  {
  public function __construct()
    {
    $this->sweet = array('a' => 'apple', 'b' => 'banana');
    $this->fruits = array('sweet' => $this->sweet, 'sour' => 'lemon');

    $this->leaves = 0;

    array_walk_recursive($this->fruits, 'LeaveCounter::incrementLeaves');

    echo $this->leaves;
    }

  public function incrementLeaves($item, $key)
    {
    $this->leaves += 1;
    }
  }

This counts apple, banana and lemon, so it returns 3.

查看更多
SAY GOODBYE
4楼-- · 2019-06-27 20:51

this could solve your problem of "NUMBER OF LEAVES" for each node of my array. This entry should count ALL the leaves of all the subnodes of the node"

its from php manual `$food = array('fruits' => array('orange', 'banana', 'apple'), 'veggie' => array('carrot', 'collard', 'pea'));

     // recursive count
     echo count($food, COUNT_RECURSIVE); // output 8

     // normal count
     echo count($food); // output 2`
查看更多
神经病院院长
5楼-- · 2019-06-27 21:06

You can do it easily as :

$leaves = 0;
array_walk_recursive($yourArray, function ($leaves) use (&$leaves) {
  $leaves++;
});

Example :

$foods = array(
  'fruits' => array('orange', 'banana', 'apple'),
  'veggie' => array('carrot', 'collard', 'pea')
);

$leaves = 0;
array_walk_recursive($foods, function ($leaves) use (&$leaves) {
  $leaves++;
});
echo $leaves; // will output 6
查看更多
登录 后发表回答