对数据行进行分组,并在每组中对一列求和并连接另一列

时间:2021-01-25 15:43:09

标签: php multidimensional-array concatenation grouping array-sum

在 php 中,我有一个关联行的索引数组,如下所示:

$the_array = [
   ['id' => 1, 'value' => 10, 'name' => 'apple'],
   ['id' => 1, 'value' => 20, 'name' => 'orange'],
   ['id' => 1, 'value' => 30, 'name' => 'banana'],
   ['id' => 2, 'value' => 100, 'name' => 'car'], 
   ['id' => 2, 'value' => 200, 'name' => 'bicycle'],
];

我想通过对 id 值进行分组来重组它,并且在每个组中我想对 value 值求和并制作一个逗号分隔的 {{1} 字符串} 值。

name

这是我试过的:

[
    ['id' => 1, 'value' => 60,  'name' => 'apple,orange,banana'],
    ['id' => 2, 'value' => 300, 'name' => 'car,bicycle']
]

它不起作用,结果错误/不完整。

3 个答案:

答案 0 :(得分:1)

我会创建一个中间数组,它首先按 id 分组为数组键,然后使用它来调用 array_column()array_sum()implode() 的组合来生成您的总和value 和组合的 name 字符串。

$temp_array = [];
foreach ($the_array as $init) {
  // Initially, group them on the id key as sub-arrays
  $temp_array[$init['id']][] = $init;
}

$result = [];
foreach ($temp_array as $id => $arr) {
  // Loop once for each id ($temp_array has 2 elements from your sample)
  // And add an element to $result
  $result[] = [
    'id' => $id,
    // Sum the value subkeys
    // array_column() returns just the key 'value' as an array
    // array_sum() adds them
    'value' => array_sum(array_column($arr, 'value')),
    // implode the name subkeys into a string
    'name' => implode(',', array_column($arr, 'name'))
  ];
}

print_r($result);
Array
(
    [0] => Array
        (
            [id] => 1
            [value] => 60
            [name] => apple,orange,banana
        )

    [1] => Array
        (
            [id] => 2
            [value] => 300
            [name] => car,bicycle
        )

)

答案 1 :(得分:1)

虽然已经回答了这个问题,但这里有另一种方法可以在一个循环中完成所有这些。

如果您跟踪将原始 ID 映射到其各自数组索引的小地图。

$result = [];
$map = [];

foreach ($the_array as $subarray) {
    $id = $subarray['id'];

    // First time we encounter the id thus we can safely push it into result
    if (!key_exists($id, $map)) {
        // array_push returns the number of elements
        // since we push one at a time we can directly get the index.
        $index = array_push($result, $subarray) - 1;
        $map[$id] = $index;

        continue;
    }

    // If the id is already present in our map we can simply
    // update the running sum for the values and concat the
    // product names.
    $index = $map[$id];
    $result[$index]['value'] += $subarray['value'];
    $result[$index]['name'] .= ",{$subarray['name']}";
}

echo '<pre>';
print_r($result);
echo '</pre>';

结果:

Array
(
    [0] => Array
        (
            [id] => 1
            [value] => 60
            [name] => apple,orange,banana
        )
    [1] => Array
        (
            [id] => 2
            [value] => 300
            [name] => car,bicycle
        )
)

答案 2 :(得分:0)

没有必要编写多个循环或保留索引映射。最精简、直接的方法是根据分组的值使用临时的第一级键。

以下两个片段生成相同的输出并具有相同的内部处理。两个片段之间的唯一区别是,一个使用语言结构迭代输入数据,另一个使用函数迭代。

当您遍历数据时,根据每一行的 id 值将临时键应用于结果数组。如果第一次遇到给定的id,则将整行数据存入组中。如果不是第一次遇到给定的 id,则将 value 值添加到先前的 value 值并将新的 name 值连接到先前存储的 {{1} } 组中的值。

完成后,您可能希望通过调用 name 重新索引第一级。

经典array_values():(Demo)

foreach()

带有 $result = []; foreach ($the_array as $row) { if (!isset($result[$row['id']])) { $result[$row['id']] = $row; } else { $result[$row['id']]['value'] += $row['value']; $result[$row['id']]['name'] .= ",{$row['name']}"; } } var_export(array_values($result)); 的函数式风格:(Demo)

array_reduce()