我需要将二维数组中的行数据按一列进行分组,然后分别对其他列进行求和,以生成一个行数可能更少的新二维数组。
就我而言,我需要按每个
[num]
计算 [price]
和 [group]
的总和。
[
['group' => 'Apple', 'num' => 5, 'price' => 10],
['group' => 'Apple', 'num' => 2, 'price' => 8],
['group' => 'Orange', 'num' => 4, 'price' => 6],
['group' => 'Orange', 'num' => 12, 'price' => 24],
]
结果会是这样的:
[
['group' => 'Apple', 'num' => 7, 'price' => 18],
['group' => 'Orange', 'num' => 16, 'price' => 30],
]
简单的循环和关联数组就可以完成这项工作:
$result = Array();
foreach($array as $row) {
if(!isset($result[ $row['group'] ])) {
$result[ $row['group'] ] = $row;
continue ;
}
$result[ $row['group'] ]['num'] += $row['num'];
$result[ $row['group'] ]['price'] += $row['price'];
}
$result = array_values($result);
使用
array_reduce()
:
$reduced = array_reduce($array, function(&$result, $item){
$result[$item['group']]['num'] += $item['num'];
$result[$item['group']]['price'] += $item['price'];
return $result;
});
通过将引用变量推入每个唯一组的结果数组中,循环后无需重新索引结果数组。
代码:(演示)
$result = [];
foreach ($array as $row) {
if (!isset($ref[$row['group']])) {
$ref[$row['group']] = $row;
$result[] =& $ref[$row['group']];
continue;
}
$ref[$row['group']]['num'] += $row['num'];
$ref[$row['group']]['price'] += $row['price'];
}
var_export($result);
作为 @Peter 解决方案的替代实现,在调用
array_values()
(运行另一个内部循环)重新索引结果之前,可以将每行的各个值单独推入结果数组中。
代码:(演示)
$result = [];
foreach ($array as ['group' => $g, 'num' => $n, 'price' => $p]) {
$result[$g]['group'] = $g;
$result[$g]['num'] = ($result[$g]['num'] ?? 0) + $n;
$result[$g]['price'] = ($result[$g]['price'] ?? 0) + $p;
}
var_export(array_values($result));
最后,此页面上任何带有
foreach()
循环的工作实现都可以使用 array_reduce()
适当地转录为函数式风格。这有点冗长,但消除了向全局范围添加临时变量的情况。
代码:(演示)
var_export(
array_values(
array_reduce(
$array,
function ($result, $row) {
if (!isset($result[$row['group']])) {
$result[$row['group']] = $row;
} else {
$result[$row['group']]['num'] += $row['num'];
$result[$row['group']]['price'] += $row['price'];
}
return $result;
}
)
)
);