【问题标题】:How to sum array value of duplicate data如何对重复数据的数组值求和
【发布时间】:2016-09-01 07:43:00
【问题描述】:

我有一个数组,其具有一些相同的ID 值,如下所示。

[
    {"ID":"126871","total":"200.00","currency":"USD","name":"John"},
    {"ID":"126872","total":"2000.00","currency":"Euro","name":"John"},
    {"ID":"126872","total":"1000.00","currency":"Euro","name":"John"},
    {"ID":"126872","total":"500.00","currency":"USD","name":"John"},
    {"ID":"126872","total":"1000.00","currency":"Euro","name":"John"},
]

如果ID 值重复,则将相同currency 的总值相加。对于同一个ID的不同currency,不用求和total

这就是我想要的。

[
    {"ID":"126871","total":"200.00","currency":"USD","name":"John"},
    {"ID":"126872","total":"4000.00","currency":"Euro","name":"John"},
    {"ID":"126872","total":"500.00","currency":"USD","name":"John"}
]

我被上述问题困住了。我已经尽可能地尝试了。但我得到了错误的结果。我非常感谢任何建议。

【问题讨论】:

  • 看起来像 JS 对象数组。
  • “我已经尽我所能尝试了” - 那么,与我们分享您的尝试,我们或许可以提供帮助。我们不会为您完成所有工作。

标签: php arrays json sum grouping


【解决方案1】:

@Cloud 我已经为您的要求制作了功能,感谢@M。 I. 看看这个总和部分。

$array = array(
    array("ID"  => "126871","total"=>"200.00","currency"=>"USD","name"=>"John"),
    array("ID"  => "126872","total"=>"2000.00","currency"=>"Euro","name"=>"John"),
    array("ID"  => "126872","total"=>"1000.00","currency"=>"Euro","name"=>"John"),
    array("ID"  => "126872","total"=>"500.00","currency"=>"USD","name"=>"John"),
    array("ID"  => "126872","total"=>"1000.00","currency"=>"Euro","name"=>"John"),
);
echo "<pre>";
print_r($array);

function unique_multidim_array($array, $key,$key1,$addedKey) { 
    $temp_array = array(); 
    $i = 0; 
    $key_array = array(); 
    $key1_array = array(); 

    foreach($array as $val) { 
        if (!in_array($val[$key], $key_array) && !in_array($val[$key1], $key1_array)) { 
            $key_array[$i] = $val[$key]; 
            $key1_array[$i] = $val[$key1]; 
            $temp_array[$i] = $val; 
        }else{
            $pkey = array_search($val[$key],$key_array);
            $pkey1 = array_search($val[$key1],$key1_array);
            if($pkey==$pkey1){
                $temp_array[$pkey][$addedKey] += $val[$addedKey];
            }else{
                $key_array[$i] = $val[$key]; 
                $key1_array[$i] = $val[$key1]; 
                $temp_array[$i] = $val; 
            }
            // die;
        }
        $i++; 
    } 
    return $temp_array; 
} 

$nArray = unique_multidim_array($array,"ID","currency","total");
// die;
print_r($nArray);
die;

【讨论】:

    【解决方案2】:

    你需要:

    • 使用json_decode将您的json字符串转换为php数组。
    • 遍历行并使用复合临时键对它们进行分组。换句话说,从每一行的 IDcurrency 值生成一个字符串,并将该字符串用作临时唯一键。
    • 对分组行的total 值求和。
    • 然后通过重新索引行并调用 json_encode() 来准备输出数组以返回 json。

    代码:(Demo)

    $json='[
        {"ID":"126871","total":"200.00","currency":"USD","name":"John"},
        {"ID":"126872","total":"2000.00","currency":"Euro","name":"John"},
        {"ID":"126872","total":"1000.00","currency":"Euro","name":"John"},
        {"ID":"126872","total":"500.00","currency":"USD","name":"John"},
        {"ID":"126872","total":"1000.00","currency":"Euro","name":"John"}
    ]';
    
    $array=json_decode($json,true);  // convert to array
    foreach($array as $row){
        if(!isset($result[$row['ID'].$row['currency']])){
            $result[$row['ID'].$row['currency']]=$row;  // on first occurrence, store the full row
        }else{
            $result[$row['ID'].$row['currency']]['total']+=$row['total'];  // after first occurrence, add current total to stored total
        }
    }
    $result=json_encode(array_values($result));  // reindex the array and convert to json
    echo $result;  // display
    

    输出:

    [
        {"ID":"126871","total":"200.00","currency":"USD","name":"John"},
        {"ID":"126872","total":4000,"currency":"Euro","name":"John"},
        {"ID":"126872","total":"500.00","currency":"USD","name":"John"}
    ]
    

    【讨论】:

      【解决方案3】:

      内容:创建一个按“ID”和“货币”分组的数组。为重复累积货币。

      如何:

      • 一次将一行添加到输出数组。
      • 如果组不在数组中,则添加它
      • 如果它在数组中,则将货币添加到现有记录中。

      Demonstration at eval.in

      代码:

      /** ----------------------------------------------
      * Create an output array one row at a time.
      * 
      * Group by Id and currency.   
      * 
      * @param array $groups
      * 
      * @return array
      */
      function getCurrencyGroups(array $groups)
      {
          $currencyGroups = array();
      
          foreach ($groups as $item) {
      
              $id       = $item['ID'];
              $currency = $item['currency'];
              $amount   = $item['total'];
      
              if (!isset($currencyGroups[$id][$currency])) {
                  $currencyGroups[$id][$currency] = $amount;
              }
              else {
                  $currencyGroups[$id][$currency] += $amount;
              }
          }
      
          return $currencyGroups;
      }
      

      运行它:

      $currencyGroups = getCurrencyGroups($source);
      

      输出:

      array (size=2)
        126871 => 
          array (size=1)
            'USD' => string '200.00' (length=6)
      
        126872 => 
          array (size=2)
            'Euro' => float 4000
            'USD' => string '500.00' (length=6)
      

      【讨论】:

        【解决方案4】:

        我发现自己处于类似的情况,除了我把自己画在一个角落里并且需要使用相同的数组进行输入和输出。我还发现 Manish 的反应有点强硬。

        foreach($open_po_report as $pkey => &$po_line){
            foreach($open_po_report as $dkey => $dupe_item){
                //do not compare the exact same line
                if($dupe_item['PoNo'].$dupe_item['Line'] === $po_line['PoNo'].$po_line['Line']){
                    continue;
                }
                //once you find a duplicate sum the qty to the original occurance
                if($dupe_item['ItemVendorItem'] === $po_line['ItemVendorItem']){
                    $po_line['MyOrder']+=$dupe_item['MyOrder'];
                    unset($open_po_report[$dkey]);
                }
                //delete the duplicate entry
            }
        }
        

        【讨论】:

          【解决方案5】:

          @Cloud 试试这个。

          $array = array(array("ID"   => "126871","total"=>"200.00","currency"=>"USD","name"=>"John",),array("ID" => "126871","total"=>"200.00","currency"=>"USD","name"=>"John",),array("ID" => "126872","total"=>"1000.00","currency"=>"Euro","name"=>"John",));
              echo "<pre>";
              print_r($array);
              $unique = array_map('unserialize', array_unique(array_map('serialize', $array)));
          

          当然@Magnus Eriksson。我正在解释为什么我们在步骤中使用“序列化”和“反序列化”:

          第一步:将多维数组转换为一维数组

          要将多维数组转换为一维数组,首先要生成数组内部所有元素(包括嵌套数组)的字节流表示。 serialize() 函数可以生成一个值的字节流表示。要生成所有元素的字节流表示,请在 array_map() 函数内调用 serialize() 函数作为回调函数。无论多维数组有多少层,结果都是一维数组。

          第 2 步:使值独一无二

          要使这个一维数组唯一,请使用array_unique() 函数。

          第三步:还原为多维数组

          虽然数组现在是唯一的,但值看起来像字节流表示。要将其还原为多维数组,请使用unserialize() 函数。

          我现在希望我为什么要编写此代码。

          【讨论】:

          • 我可能不像我想象的那样理解array_map,但是unserializeserialize 适合在哪里呢?您应该真正解释一下代码实际上在做什么,而不仅仅是发布一些随机代码 sn-p。
          • 我认为 OP 希望对具有相同 ID 的行的“总计”字段求和。我认为这需要更多的解析:(
          • 这段代码被证明是不正确的,只会让研究人员感到困惑。证明:3v4l.org/lWA8Z 这会破坏数据,不会求和。
          猜你喜欢
          • 1970-01-01
          • 2019-09-04
          • 1970-01-01
          • 2018-07-08
          • 1970-01-01
          • 1970-01-01
          • 2018-07-26
          • 2020-01-16
          • 2019-01-22
          相关资源
          最近更新 更多