2010-05-05 48 views
0

如何递归地找到类似这样的数组的所有子元素的总值?通过索引键聚合多维数组的优雅方式

[0] => Array 
    (
     [value] => ? // 8590.25 + 200.5 + 22.4 
     [children] => Array 
      (
       [0] => Array 
        (
         [value] => ? // 8590.25 + 200.5 
         [children] => Array 
          (
           [0] => Array 
            (
             [value] => 8590.25 // leaf node 
            ) 
           [1] => Array 
            (
             [value] => 200.05 // leaf node 
            ) 
          ) 

        ) 
       [1] => Array 
        (
         [value] => 22.4 // leaf node 
        ) 
      ) 
    ) 
+0

你能提供一个'var_export'或数组的普通PHP版本:它是否有实际的'value'和'children'项目,还是只是说明如何计算值? – salathe 2010-05-05 19:31:00

+0

实际数据是包含树的RecursiveIterator对象 - 我只是使用关联数组来简化“如何在多维数据类型中递归聚合叶节点”的问题。所以具体的实现对我来说并不重要 - 我只需要一个算法。 – 2010-05-05 20:08:52

回答

1

这是种类的情况下,我会使用类而不是数组。这样,你可以有一个getValue()方法(或者使用magic来定义使用__get的value属性),它可以根据需要对子值进行求和。如果你保证某个点后的东西不会改变,你可以缓存这些子和以避免重复计算。也许这样?

class DataStructure 
{ 
    private $children = array(); 
    private $value = 0; 

    public function __construct ($value = 0) 
    { 
    $this->value = $value; 
    } 

    public function getValue() 
    { 
    $total = $this->value; 
    foreach ($this->children as $child) 
    { 
     $total += $child->getValue(); 
    } 
    return $total; 
    } 

    public function addChild (DataStructure $child) 
    { 
    $this->children[] = $child; 
    } 
} 
+0

有趣的是,树是一个RecursiveIterator(类DataStructure实现了RecursiveIterator),我试图在一个扩展了DataStructure的类中进行聚合(类AggregateDatastructure extends DataStructure)..我必须再看一下这个东西.. :-P – 2010-05-05 20:00:55

+0

很酷。然后,我打赌你可以通过添加一两种方法来实现这一点,一旦你理清了实现的细节。想法是这样的:不要让一段代码遍历所有的深度,而是要问每个孩子同样的问题,他们会回过头去问问他们的孩子...... – grossvogel 2010-05-05 20:21:29

1

这会给你的叶节点值的总和:

$sum = 0; 
array_walk_recursive($arr, create_function('$v, $k, $sum', '$sum[0] += $v;'), array(&$sum)); 

等效采用匿名函数(PHP 5.3+):

$sum = 0; 
array_walk_recursive($arr, function ($v) use (&$sum) { $sum += $v; });