【问题标题】:PHP: Accumulate values in associative arrayPHP:在关联数组中累积值
【发布时间】:2019-05-13 12:13:43
【问题描述】:

我想根据键的一部分在关联数组中累积值。

我已经测试了这个在索引数组中工作正常的 foreach 循环:

$b = array();

foreach ($a as $key => $value) {
  if ($key > 0) {
    $b[$key] = $b[$key - 1] + $value;
  }
}

我无法让它在关联数组中工作,但是...

$a(摘录)

Array ( 
    [2014-04-22|Paul] => 0 
    [2014-04-28|Paul] => 2 
    [2014-05-13|Paul] => 0
    [2014-06-03|Paul] => 1 
    [2014-06-12|Paul] => 0 
    [2014-08-11|Paul] => 1 
    [2014-08-28|Paul] => 3 
    [2012-05-09|John] => 1 
    [2012-08-29|John] => 2 
    [2012-09-05|John] => 0 
    [2012-09-13|John] => 1 
)

$b(想要的结果)

Array ( 
    [2014-04-22|Paul] => 0 
    [2014-04-28|Paul] => 2 
    [2014-05-13|Paul] => 2 
    [2014-06-03|Paul] => 3 
    [2014-06-12|Paul] => 3 
    [2014-08-11|Paul] => 4 
    [2014-08-28|Paul] => 7 
    [2012-05-09|John] => 1 
    [2012-08-29|John] => 3 
    [2012-09-05|John] => 3 
    [2012-09-13|John] => 4 
)

在期望的结果中,每个值都是 'Paul' 和 'John'(以及更多)累积到前一个值。

【问题讨论】:

  • 这是因为数组由很多人组成,先按人排序,再按日期排序。
  • 请注意,如果您创建累积值数组,则不需要对名称进行排序

标签: php arrays accumulate


【解决方案1】:

您可以通过跟踪键的名称部分来做到这一点,并在获得新名称时重置总数:

$b = array();
$lastname = '';
foreach ($a as $key => $value) {
    list($d, $n) = explode('|', $key);
    if ($n == $lastname) {
        $total += $value;
    }
    else {
        $total = $value;
    }
    $b[$key] = $total;
    $lastname = $n;
}
print_r($b);

输出:

Array ( 
    [2014-04-22|Paul] => 0 
    [2014-04-28|Paul] => 2 
    [2014-05-13|Paul] => 2 
    [2014-06-03|Paul] => 3 
    [2014-06-12|Paul] => 3 
    [2014-08-11|Paul] => 4 
    [2014-08-28|Paul] => 7 
    [2012-05-09|John] => 1 
    [2012-08-29|John] => 3 
    [2012-09-05|John] => 3 
    [2012-09-13|John] => 4 
)

Demo on 3v4l.org

【讨论】:

    【解决方案2】:

    通过使用array_walk,检查当前名称是否与下一个名称相同,因为我正在通过下一个重置值。

    $result = [];
    $tempKey = '';
    $arr = array_walk($arr, function($item, $key) use(&$result, &$tempKey, &$total){
        list($date, $name) = explode("|", $key); // explode key
        if(empty($tempKey) || $tempKey != $name){ // if empty or if conflict
            $tempKey = $name; // tempKey for reference
            $total = $item; // total reset to current value
        }else{
            $total += $item; // adding for same name
        }
        $result[$key] = $total; // putting calculated value
    });
    
    print_r($result);
    

    输出

    Array
    (
        [2014-04-22|Paul] => 0
        [2014-04-28|Paul] => 2
        [2014-05-13|Paul] => 2
        [2014-06-03|Paul] => 3
        [2014-06-12|Paul] => 3
        [2014-08-11|Paul] => 4
        [2014-08-28|Paul] => 7
        [2012-05-09|John] => 1
        [2012-08-29|John] => 3
        [2012-09-05|John] => 3
        [2012-09-13|John] => 4
    )
    

    Demo.

    【讨论】:

    • 这最终会比简单的foreach 慢,因为数组中每个值的函数调用开销很大。
    • @Nick 感谢您的关注。实际上你是对的 :) 我会从下一次开始处理这个问题。它正在为我学习。
    • 如果我对性能感到好奇,我通常会使用我在this answer中显示的代码来比较不同的方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多