skip to Main Content

I have three Collections with the same keys and different numeric values, and I’d like to sum them together.
e.g.

$broadInventory = {'horse': 300, 'cow': 400, 'entropy': 400};
$ericaInventory = {'horse': 10, 'cow': 20, 'entropy': 30};
$johnsonInventory = {'horse': 5, 'cow': 9, 'entropy': 3};

and I’m looking for this result:

{'horse': 315, 'cow': 429, 'entropy': 433};

I figured this would be easy, but it’s turned out harder than I thought!

EDIT: Thanks to Abdulla, this is the answer I came up with:

    private function sumCollections(Collection ...$collections) {
        $merge = collect($collections);
        $keys = $collections[0]->keys();

        return $merge->pipe(
            static function ($item) use ($keys) {
                return collect([
                    $keys->mapWithKeys(fn($key) => [$key => $item->sum($key)])
                ]);
            }
        );
    }

2

Answers


  1. First of all, that is wrong array/collection syntax you wrote up there.
    convert all the collections to arrays using the toArray() function. Then use the array_merge_recursive() to merge the arrays so you get one single array with 3 keys. Then loop through the array and sum the values, appending each value to a the same array. Here is the explanation in code:

    $broadInventory = collect(['horse' => 300, 'cow' => 400, 'entropy' => 400]);
    $ericaInventory = collect(['horse' => 10, 'cow' => 20, 'entropy' => 30]);
    $johnsonInventory = collect(['horse' => 5, 'cow' => 9, 'entropy' => 3]);
    
    $broadInventory = $broadInventory->toArray();
    $ericaInventory = $ericaInventory->toArray();
    $johnsonInventory = $johnsonInventory->toArray();
    
    $new_array = array_merge_recursive($broadInventory, $ericaInventory, $johnsonInventory);
    
    foreach(array_keys($new_array) as $key) {
       
    $new_array[$key] = array_sum($new_array[$key]);
    
    }
    $new_colection = collect($new_array);
    
    dd($new_collection);
    
    
    

    will give you:

    ^ IlluminateSupportCollection {#1269 ▼
      #items: array:3 [▼
        "horse" => 315
        "cow" => 429
        "entropy" => 433
      ]
      #escapeWhenCastingToString: false
    }
    
    Login or Signup to reply.
  2. Bit tricky, but it works. By using pipe() with collection iteration.

    # assume as given collection =
    $broadInventory = collect(['horse' => 300, 'cow' => 400, 'entropy' => 400]);
    $ericaInventory = collect(['horse' => 10, 'cow' => 20, 'entropy' => 30]);
    $johnsonInventory = collect(['horse' => 5, 'cow' => 9, 'entropy' => 3]);
    
    # Mergeing three collections into one
    $merge = collect([$broadInventory, $ericaInventory, $johnsonInventory]);
    
    # looping through the collection
    $sum = $merge->pipe(static function ($item) {
        return collect([
            'horse' => $item->sum('horse'),
            'cow' => $item->sum('cow'),
            'entropy' => $item->sum('entropy'),
        ]);
    });
    
    print_r($sum);
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search