合并两个 Laravel 集合并对值求和

4

我有10个集合(以下示例中使用了3个),需要按键合并,但需要对值求和。我的集合如下:

[
    'key1' => ['value1' => 5, 'value2' => 3, 'value3' => 0],
    'key2' => ['value1' => 1, 'value2' => 6, 'value3' => 2],
    'key3' => ['value1' => 0, 'value2' => 0, 'value3' => 1],
]

[
    'key1' => ['value1' => 3, 'value2' => 1, 'value3' => 7],
    'key2' => ['value1' => 1, 'value2' => 3, 'value3' => 2],
    'key3' => ['value1' => 1, 'value2' => 6, 'value3' => 1],
]

[
    'key1' => ['value1' => 2, 'value2' => 3, 'value3' => 9],
    'key2' => ['value1' => 3, 'value2' => 8, 'value3' => 3],
    'key3' => ['value1' => 1, 'value2' => 0, 'value3' => 6],
]

我希望获得一个这样的集合,其结果看起来像这样:
[
    'key1' => ['value1' => 10, 'value2' => 7, 'value3' => 16],
    'key2' => ['value1' => 5, 'value2' => 17, 'value3' => 7],
    'key3' => ['value1' => 2, 'value2' => 6, 'value3' => 8],
]

有没有我错过的内置Laravel Collection方法,或者最好的方法是什么?

编辑:(更多信息)值始终为数字。任何集合中都没有字符串值。

编辑2:一些人问我尝试了什么。我尝试了这个,它有效:

$merged = [];
foreach ($seeds as $seed) {
    foreach ($seed as $location => $values) {
        foreach ($values as $key => $value) {
            $merged[$location][$key] = $value + ($merged[$location][$key] ?? 0);
        }
    }
}

我只是想知道是否有更简洁的方法来实现同样的功能,而不是使用3个foreach循环。


1
你真的尝试过什么吗?你取得了多大进展,你尝试了什么? - Option
1
你能向我们展示你为实现这个目标所做出的努力吗? - Rahul
可能是Sum array values of the same key的重复问题。 - user9025311
@Option 请查看我的编辑 - Ryan Mortier
@rahulsm,请查看我的修改。 - Ryan Mortier
2个回答

1
我使用 Laravel 7 完成了这个操作,如果有人需要,可以尝试。
$test = collect([
   [
     'key1' => ['value1' => 5, 'value2' => 3, 'value3' => 0],
     'key2' => ['value1' => 1, 'value2' => 6, 'value3' => 2],
     'key3' => ['value1' => 0, 'value2' => 0, 'value3' => 1],
   ],

   [
     'key1' => ['value1' => 3, 'value2' => 1, 'value3' => 7],
     'key2' => ['value1' => 1, 'value2' => 3, 'value3' => 2],
     'key3' => ['value1' => 1, 'value2' => 6, 'value3' => 1],
   ],

   [
     'key1' => ['value1' => 2, 'value2' => 3, 'value3' => 9],
     'key2' => ['value1' => 3, 'value2' => 8, 'value3' => 3],
     'key3' => ['value1' => 1, 'value2' => 0, 'value3' => 6],
   ]
]);
$col = $test->reduce(function ($carry, $item) {
    return $carry->mergeRecursive($item);
}, collect([]));
$col->transform(function($item) {
    return collect($item)->map(function ($item2) {
        return collect($item2)->sum();
    });
});

0

真的以为会有比循环更简单的方法,但似乎这个解决方案仍然比我想出来的更好。即使您更改深度,Flatten也会删除键,而mapToGroups仅在返回包含单个键/值对的关联数组时起作用,pluck带来其他困难等等。

以下是我想出来的方法

$test = collect([
   [
     'key1' => ['value1' => 5, 'value2' => 3, 'value3' => 0],
     'key2' => ['value1' => 1, 'value2' => 6, 'value3' => 2],
     'key3' => ['value1' => 0, 'value2' => 0, 'value3' => 1],
   ],

   [
     'key1' => ['value1' => 3, 'value2' => 1, 'value3' => 7],
     'key2' => ['value1' => 1, 'value2' => 3, 'value3' => 2],
     'key3' => ['value1' => 1, 'value2' => 6, 'value3' => 1],
   ],

   [
     'key1' => ['value1' => 2, 'value2' => 3, 'value3' => 9],
     'key2' => ['value1' => 3, 'value2' => 8, 'value3' => 3],
     'key3' => ['value1' => 1, 'value2' => 0, 'value3' => 6],
   ]
]);
$mappedCollection = collect($test->first())->keys()->mapWithKeys(function($item,$key) use($test){
   return[
      $item => $test->map(function ($mapItem, $mapKey) use($item) {         
         return $mapItem[$item];
      })
   ];
})->mapWithKeys(function($item,$key){
   $eachLine = collect($item->first())->keys()->mapWithKeys(function($mapItem) use($item){
      return[ $mapItem => $item->sum($mapItem)  ];
   });       
   return [$key =>  $eachLine];
})->all();

dd($mappedCollection);

集合文档的源代码https://laravel.com/docs/5.6/collections


似乎这是一种残酷的方法,但我接受了它作为答案,因为您成功使用Laravel的Collections实现了它。不过,最终我还是只使用了三个foreach循环。 - Ryan Mortier
完全同意使用foreach循环会更容易。也许在laravel集合中有一种更好(不那么明显)和更容易的方法,但我将把它留给laravel的Jon Skeet ^^ - Sérgio Reis
为什么不直接使用 map 和 reduce 呢? - DC-

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接