【问题标题】:Multidimensional array sum values多维数组和值
【发布时间】:2016-03-08 08:46:21
【问题描述】:

我有以下函数来对多维数组值求和。

// summing values of multidimensional array
function getSum($array, $path = array()){
    // process second argument:
    foreach ($path as $key) {
        if (!is_array($array) || !isset($array[$key])) {
            return 0; // key does not exist, return 0
        }
        $array = $array[$key];
    }
    if(is_array($array)) {
        $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
        $sum = 0;
        foreach ($iterator as $key => $value) {
            $sum += $value;
        }
    } else{
        $sum = $array;
    }
    return $sum;
}

我正在使用这样的功能:

$array = array();
$array['one']['green'][20] = 20;
$array['one']['blue'][20] = 5;
$array['one']['blue'][30] = 10;

getSum($array,['one','green']); // 20
getSum($array,['one','blue',20]); // 5

现在,如果我不想设置任何特殊颜色,我会遇到问题,因为我希望该脚本将所有颜色的类别 20 中的所有值相加。

所以它应该像这样工作:

getSum($array,['one','*',20]); // 25

感谢您的帮助!

这是我的数组的示例:

Array ( 
    [1] => Array ( 
        [AREA I] => Array (
            [20] => 1 
            [25] => 0 
            [30] => 0 ) 
        [AREA II] => Array ( 
            [20] => 0 
            [30] => 0 ) 
        [AREA III] => Array ( 
            [20] => 2 
            [30] => 0 ) 
        [AREA IV] => Array ( 
            [20] => 0 
            [30] => 3 ) 
        [AREA V] => Array ( 
            [20] => 4 
            [25] => 0 
            [30] => 3 )  
    ) 
    [2] => Array ( 
        [AREA I] => Array ( 
            [20] => 0 
            [30] => 0 ) 
        [AREA II] => Array ( 
            [20] => 0 
            [30] => 0 ) 
    )
)

这是我的getSum 通话示例:

getSum($visitsandinfosact,['*','*',20]); // should print 7

【问题讨论】:

  • 这样的数组$array['one'] = 10; $array['one']['green'] = 20; 不能存在。 $array['one'] 要么是数组要么是标量值
  • @splash58:我编辑了我的代码示例。

标签: php arrays recursion multidimensional-array


【解决方案1】:

递归函数

我不确定['one','*'] 是否应该给出 45,但如果它应该只返回 0,那么您只需删除 else if (empty($filterList) && is_array($value) && $first == "*") 条件。所有不是数组的值都通过intval 转换为 int 并添加到总和中。如果您想使用浮点数,请使用 floatval 而不是 intval

function getSum($array, $filterList = array('*')) {
    $sum = 0;
    $first = array_shift($filterList);
    foreach ($array as $key => $value) {
        if ($key == $first || $first == "*") {
            if (is_array($value) && !empty($filterList)) {
                $sum += getSum($value, $filterList);
            } else if (empty($filterList) && is_array($value)) {
                $sum += getSum($value, array("*"));
            } else if (empty($filterList)) {
                $sum += intval($value);
            }
        }
    }
    return $sum;
}

echo getSum($array,['one','*',20], 10) . "\n"; // 25
echo getSum($array,['one','*','*',20]) . "\n"; // 10
echo getSum($array,['one','*']) . "\n"; // 45
echo getSum($array) . "\n"; // 45

输入数组

$array = array();
$array['one'] = array();
$array['one']['green'] = array();
$array['one']['green'][20] = 20;
$array['one']['blue'] = array();
$array['one']['blue'][20] = 5;
$array['one']['blue'][30] = 10;
$array['one']['orange']['red'][20] = 10;

输出

只输出数字,只是添加了输入参数以便更好地理解。

25 // (['one','*',20])
10 // (['one','*','*',20])
45 // (['one','*'])
45 // no filterList

【讨论】:

  • 如果我只写getSum($array),这不会返回任何内容
  • @lingo 是的,然后出现错误,因为接口是这样定义的。你想把它写成function getSum($array, $filterList = array())我会把它添加到代码中,但我认为它没有必要。如果 filterList 为空,则应返回 0,因为我了解您的要求!
  • @lingo 刚刚更新了它,你想在算法中返回 45 ......所以我更新了代码,只需复制并再次粘贴!
  • @lingo 我正在执行代码,它工作正常。你能粘贴getSum的调用吗,就像你修改了标题一样
【解决方案2】:

简而言之,您需要一个递归函数来添加通配符“端点”。您也可以使用相同的递归性质来覆盖加法。

以下应该做你想要的:

// summing values of multidimensional array
function getSum(&$array, $path = array()){
    $sum = 0;
    if(is_int($array) and empty($path)) // return value if int
        $sum = $array;
    else if(is_array($array)){ // else add recurred values
        if(empty($path)){
            foreach($array as $value)
                $sum += getSum($value);
        } else {
            $key = array_shift($path);
            if($key=='*'){
                foreach($array as $value)
                    $sum += getSum($value, $path);
            } else {
                if(isset($array[$key]))
                    $sum += getSum($array[$key], $path);
            }
        }
    }
    return $sum;
}

测试:

$array['one'] = array();
$array['one']['green'] = array();
$array['one']['green'][20] = 20;
$array['one']['blue'] = array();
$array['one']['blue'][20] = 5;
$array['one']['blue'][30] = 10;
$array['one']['orange']['red'][20] = 10;

echo getSum($array,['one','*',20]); // 25
echo getSum($array,['one','*','*',20]); // 10
echo getSum($array,['one','*']); // 45

快乐编码

【讨论】:

  • 是不是我不再需要RecursiveIteratorIteratorRecursiveArrayIterator 了?
  • @iautomation getSum($array,['one','*']); 呢?
  • @lingo 该函数的目的是覆盖通配符级别的查询。但是,由于已经在递归函数中,因此不需要插入器。
  • @iautomation if ['one','*'] 不应该给 45 或者?如果是,那么 ['one','*',20] 不应该给 35?
  • @Kordi 这与原始问题和代码示例的功能一致。尽管星号代表一个级别,但通过$path 获得的整数值是递归的,因为原始代码通过RecursiveArrayIterator 提供了一个总和。
猜你喜欢
  • 2011-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-14
  • 1970-01-01
  • 2015-10-30
  • 1970-01-01
  • 2015-10-30
相关资源
最近更新 更多