按列对 3d 数组中的数据进行分组,并对其他两列中的相关子数组数据求和

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

我正在尝试按列值对 3 维数组中的行数据进行分组,并对每个相应组中的子数组数据求和。

[
    [
        'name' => 'Edward Foo',
        'desc_topic' => ['Apple', 'Banana', 'Orange'],
        'qtd_posts' =>  [10,      20,       50      ],
    ],
    [
        'name' => 'Michael Max',
        'desc_topic' => ['Apple', 'Banana', 'Orange'],
        'qtd_posts' =>  [10,      10,       10      ],
    ],
    [
        'name' => 'Edward Foo',
        'desc_topic' => ['Apple', 'Banana', 'Orange'],
        'qtd_posts' =>  [5,       10,       30      ],
    ],
    [
        'name' => 'Michael Max',
        'desc_topic' => ['Apple', 'Banana', 'Orange'],
        'qtd_posts' =>  [8,       8,        20      ],
    ],
]

期望的输出:

[
    [
        'name' => 'Edward Foo',
        'desc_topic' => ['Apple', 'Banana', 'Orange'],
        'qtd_posts' =>  [15,      30,       80      ],
    ],
    [
        'name' => 'Michael Max',
        'desc_topic' => ['Apple', 'Banana', 'Orange'],
        'qtd_posts' =>  [18,      18,       30      ],
    ],
]
php arrays multidimensional-array sum grouping
2个回答
1
投票

我假设如下:

  1. 原始数组中的每个名称条目都有一个相同的
    desc_topic
    子数组(例如,它们在每个实例中都具有相同的Apple/Banana/Orange值。
  2. qtd_posts
    子数组在相同的对应槽中具有要分组的值(例如,所有“1”条目要加在一起,所有“2”条目加在一起,等等)
  3. 您想保留父数组键,以便所有“Edward Foo”条目都将使用 Edward Foo 条目使用的第一个键(例如 0)

如果适用,那么这样的事情应该有效:

$newarr = array();
$reverse_map = array();

foreach($array as $idx => $entry) {
    if (isset($reverse_map[$entry['name']]) {
         // have we seen this name before? retrieve its original index value
         $idx = $reverse_map[$entry['name']]; 
    } else {
         // nope, new name, so store its index value
         $reverse_map[$entry['name']] = $idx;
    }

    // copy the 'constant' values
    $newarr[$idx]['name'] = $entry['name'];
    $newarr[$idx]['desc_top'] = $entry['desc_topic'];

    // sum the qtd_post values to whatever we previously stored.        
    foreach($entry['qtd_posts'] as $x => $y) {
        $newarr[$idx]['qtd_posts'][$x] += $y;
    }
}

0
投票

我已经扩展了输入数据的可变性,因为我认为在实际项目中拥有唯一的子数组列是现实的。

为了更简单地访问行数据,我建议调用

extract()
来生成单个变量。

如果第一次遇到

name
,只需将整行保存在结果数组中(使用临时键,以便更容易识别属于同一组的后续行)。

对于同一组中的后续行,迭代

desc_topic
子数组中的条目。如果在组的
desc_topic
子数组中找到当前值,只需将相关的
qtd_posts
值添加到适当保存的
qtd_posts
值。否则,它是一个独特的主题,必须向该组的
desc_topic
qtd_posts
子数组添加一个新元素。

代码:(演示

$result = [];
foreach ($array as $row) {
    extract($row);
    if (!isset($result[$name])) {
        $result[$name] = $row;
    } else {
        foreach ($desc_topic as $i => $topic) {
            $index = array_search($topic, $result[$name]['desc_topic']);
            if ($index === false) {  // create new column in both subarrays
                $result[$name]['desc_topic'][] = $topic;
                $result[$name]['qtd_posts'][] = $qtd_posts[$i];
            } else {  // sum preexisting value with new value in on same topic
                $result[$name]['qtd_posts'][$index] += $qtd_posts[$i];
            }
        }
    }
}
var_export(array_values($result));
© www.soinside.com 2019 - 2024. All rights reserved.