2010-05-05 44 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; });