如何按“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"
}
]
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
}]
$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);
首先将对象分组:
$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);
<?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);
?>