按列对二维数组的行进行分组,并对每组中的另一列求和[重复]

问题描述 投票:0回答:4

如何按“tax”和“concept”以及SUM属性“val”对数组进行分组?

我希望在税收和概念相同时创建单个对象,并对值进行求和。

我尝试使用简单的 foreach 和内部验证,但不起作用。

echo json_encode($array);

数组打印

[
 {
    "tax": "10",
    "concept": "TUC",
    "val": "10"
 },
 {
    "tax": "10",
    "concept": "TUC",
    "val": "86"
 },
 {
    "tax": "15",
    "concept": "TUC",
    "val": "8"
 },
 {
    "tax": "11",
    "concept": "IPS",
    "val": "6"
 },
 {
    "tax": "11",
    "concept": "IPS",
    "val": "45"
 }  
]

预期结果

[
 {
    "tax": "10",
    "concept": "TUC",
    "val": "96"
 },
 {
    "tax": "15",
    "concept": "TUC",
    "val": "8"
 },
 {
    "tax": "11",
    "concept": "IPS",
    "val": "51"
 }
]
php arrays multidimensional-array sum grouping
4个回答
7
投票

您可以在这里使用

array_reduce()
。您将使用
tax
值作为分组的键,并将数组缩减为唯一的
tax
元素,同时生成
val
值的总和。这种方法唯一需要注意的是,将其转换为 JSON 将使 PHP 认为外部元素是一个对象而不是数组(即使它是一个数组,这是因为我们最终使用非默认数组索引)。但是,通过调用
array_values()
可以轻松缓解这种情况。

$array = // your array from above
$result = array_reduce($array, function($carry, $item) { 
    if(!isset($carry[$item->tax])) {
        $carry[$item->tax] = $item;
    } else {
        $carry[$item->tax]->val += $item->val;
    }
    return $carry;
});

$result = array_values($result);

echo json_encode($result);

您可以从这个演示中看到它产生的结果:

[{
    "tax": "10",
    "concept": "TUC",
    "val": 96
}, {
    "tax": "15",
    "concept": "TUC",
    "val": "8"
}, {
    "tax": "11",
    "concept": "IPS",
    "val": 51
}]

1
投票
$array // Your array 
$result = [];

array_walk($array, function($object) use (&$result) {
    $notExist = true;
    foreach ($result as $item) {
        if ($item->tax == $object->tax && $item->concept == $object->concept) {
            $item->val += $object->val;
            $notExist = false;
            break;
        }
    }
    if ($notExist) {
        array_push($result, $object);
    }
});

echo json_encode($result);

0
投票

首先将对象分组:

$groups = [];
foreach($array as $object){
    $groups[$object->tax . "\0" . $object->concept] = $object;
    // I use the NUL byte to delimit, assuming it is absent in $tax and $concept
}

然后将每个组映射到一个汇总对象中。

$output = array_map(function(array $group){
    $object = new stdClass;
    $object->tax = $group[0]->tax;
    $object->concept = $group[0]->concept;
    $object->val = array_reduce($group, function($carry, $item){
        return $carry + $item->val;
    }, 0);
    return $object;
}, $groups);

0
投票
<?php
$arr_str = '[
    {"tax":"10", "concept":"TUC", "val":"10"},
    {"tax":"10", "concept":"TUC", "val":"86"},
    {"tax":"15", "concept":"TUC", "val":"8"},
    {"tax":"11", "concept":"IPS", "val":"6"},
    {"tax":"11", "concept":"IPS", "val":"45"}
]';

$arr = json_decode($arr_str);

$tmp_array = [];

foreach ($arr as $e) {
    // combine "tax" and "concept" so we can use both of them as key. Use "_" as delimiter.
    $key = $e->tax . "_" . $e->concept;
    // sum the "val" if the key exists, otherwise assign it
    isset($tmp_array[$key]) ? $tmp_array[$key] += $e->val : $tmp_array[$key] = $e->val;
}

$grouped_array = [];

foreach ($tmp_array as $k => $v) {
    // ungroup the key so we can create an array like the original one
    $tmp = explode("_", $k);
    $grouped_array[] = (object)["tax" => $tmp[0], "concept" => $tmp[1], "val" => $v];
}

echo json_encode($grouped_array);
?>
© www.soinside.com 2019 - 2024. All rights reserved.