Home > Back-end >  Laravel Lumen Collection - Group By With Sum and preserve the values
Laravel Lumen Collection - Group By With Sum and preserve the values

Time:09-25

I'm working on Lumen and my collection has duplicate values, example:

collect([
 [
        'name' => 'John Doe',
        'department' => 'Sales',
        'phone' => '99999-99999',
        'value' => 25.0
    ],
    [
        'name' => 'Mary Lisa',
        'department' => 'Finance',
        'phone' => '88888-88888',
        'value' => 5.0
    ],
    [
        'name' => 'Mary Lisa',
        'department' => 'Finance',
        'phone' => '88888-88888',
        'value' => 58.0
    ],
    [
        'name' => 'Lucas Rodrigues',
        'department' => 'Marketing',
        'phone' => '22222-22222',
        'value' => 90.0
    ]
])

I would like to sum the value property when the name is the same but preserve other values like (department and phone) and remove duplicates entity, example:

collect([
 [
        'name' => 'John Doe',
        'department' => 'Sales',
        'phone' => '99999-99999',
        'value' => 25.0
    ],
    [
        'name' => 'Mary Lisa',
        'department' => 'Finance',
        'phone' => '88888-88888',
        'value' => 63.0
    ],
    [
        'name' => 'Lucas Rodrigues',
        'department' => 'Marketing',
        'phone' => '22222-22222',
        'value' => 90.0
    ]
])

What's the best way to do this?

CodePudding user response:

Try the following:

$newCollection = collect([]);
$collectctions = collect([
    [
        'name' => 'John Doe',
        'department' => 'Sales',
        'phone' => '99999-99999',
        'value' => 25.0
    ],
    [
        'name' => 'Mary Lisa',
        'department' => 'Finance',
        'phone' => '88888-88888',
        'value' => 5.0
    ],
    [
        'name' => 'Mary Lisa',
        'department' => 'Finance',
        'phone' => '88888-88888',
        'value' => 58.0
    ],
    [
        'name' => 'Lucas Rodrigues',
        'department' => 'Marketing',
        'phone' => '22222-22222',
        'value' => 90.0
    ]
]);

foreach ($collectctions as $item) {
    if($newCollection->contains('name', $item['name'])){
        $index = $newCollection->where('name', $item['name'])->keys()[0];

        $newCollection = $newCollection->map(function ($object, $i) use ($index, $item) {
            if($i == $index){
                $object['value']  = $item['value'];
            }

            return $object;
        });

    }
    else{
        $newCollection->push($item);
    }
}

return $newCollection;

CodePudding user response:

This can be achieved using collection functions (https://laravel.com/docs/8.x/collections). In this example I solved it using (groupBy, map, flatten, slice, count and sum).

$data = collect([
    [
        'name' => 'John Doe',
        'department' => 'Sales',
        'phone' => '99999-99999',
        'value' => 25.0
    ],
    [
        'name' => 'Mary Lisa',
        'department' => 'Finance',
        'phone' => '88888-88888',
        'value' => 5.0
    ],
    [
        'name' => 'Mary Lisa',
        'department' => 'Finance',
        'phone' => '88888-88888',
        'value' => 58.0
    ],
    [
        'name' => 'Lucas Rodrigues',
        'department' => 'Marketing',
        'phone' => '22222-22222',
        'value' => 90.0
    ]
]);

$data = $data->groupBy('name')->map(function ($item) {
    if ($item->count() > 1) {
        $item = $item->slice(0, 1)->map(function($subItem) use ($item) {
            $subItem['value'] = $item->sum('value');

            return $subItem;
        });
    }

    return $item;
})
->flatten(1);

When calling print_r($data->toArray()); we get the following array as result:

Array
(
    [0] => Array
        (
            [name] => John Doe
            [department] => Sales
            [phone] => 99999-99999
            [value] => 25
        )

    [1] => Array
        (
            [name] => Mary Lisa
            [department] => Finance
            [phone] => 88888-88888
            [value] => 63
        )

    [2] => Array
        (
            [name] => Lucas Rodrigues
            [department] => Marketing
            [phone] => 22222-22222
            [value] => 90
        )

)
  • Related