Add count of duplicate values to Laravel collection
Asked Answered
O

5

10

I don´t want to remove the duplicate values, I want to get the articles_id duplicates and sum their quantity values, for example, this is my collection:

Collection {#306 ▼
  #items: array:3 [▼
    0 => CartLine {#294 ▼
      +quantity: 2
      +article_id: 1728
      +article_name: "TAZA CERAMICA"
    }
    1 => CartLine {#296 ▼
      +parent_line_id: null
      +quantity: 1
      +article_id: 1728
      +article_name: "TAZA CERAMICA"
    }
    2 => CartLine {#298 ▼
      +quantity: 1
      +article_id: 1378
      +article_name: "JARRA CERVEZA ALEMANA"

    }
  ]
}

And I want get this result:

Collection {#306 ▼
  #items: array:3 [▼
    0 => CartLine {#294 ▼
      +quantity: 3 //sum total quantity of the duplicates elements with same article_id
      +article_id: 1728
      +article_name: "TAZA CERAMICA"
    }
    1 => CartLine {#296 ▼
      +parent_line_id: null
      +quantity: 3
      +article_id: 1728
      +article_name: "TAZA CERAMICA"
    }
    2 => CartLine {#298 ▼
      +quantity: 1
      +article_id: 1378
      +article_name: "JARRA CERVEZA ALEMANA"

    }
  ]
}

I want sum the quantities of the duplicate elements and set the quantity property with the sum in these elements.

Ochlophobia answered 30/11, 2016 at 12:17 Comment(0)
S
8

You could try something like:

$collection->groupBy('article_id')->flatMap(function ($items) {

    $quantity = $items->sum('quantity');

    return $items->map(function ($item) use ($quantity) {

        $item->quantity = $quantity;

        return $item;

    });

});

Obviously, change $collection to be whatever you've called the variable that holds your collection.

Hope this helps!

Straus answered 30/11, 2016 at 13:43 Comment(0)
B
17

I know this answer was already accepted, but I just found this StackOverflow post when I was searching for the same thing. What I ended up doing was the following.

$users = Users::all();
$usersUnique = $users->unique('id');
$usersDupes = $users->diff($usersUnique);

dd($users, $usersUnique, $usersDupes);

I only needed mine for a one time purpose so I am not sure how performant this would be if you need to use it on production page.

Bili answered 16/2, 2017 at 16:4 Comment(2)
This is incorrect. unique() method will provide ALL unique ids, removing the duplicates, so the diff of the unique collection with the original collection will always be empty.Disinfectant
This comment is incorrect.. If the original collection is different than the unique one then by definition the diff will not be empty. The diff is original->diff(unique), which is the correct way and what this answer gives and not the other way around (Which would indeed give an empty result)Ciprian
S
15

Another one solution to obtain grouped duplicates:

    $collection = collect([
        [
            'name' => 'aa',
            'value' => 22
        ],
        [
            'name' => 'bb',
            'value' => 22
        ],
        [
            'name' => 'cc',
            'value' => 11
        ],
        [
            'name' => 'bb',
            'value' => 33
        ],
        [
            'name' => 'bb',
            'value' => 33
        ],
        [
            'name' => 'bb',
            'value' => 33
        ],
    ]);

    $groupedByValue = $collection->groupBy('value');

    $dupes = $groupedByValue->filter(function (Collection $groups) {
        return $groups->count() > 1;
    });

Output:

array:2 [▼
  22 => array:2 [▼
    0 => array:2 [▼
      "name" => "aa"
      "value" => 22
    ]
    1 => array:2 [▼
      "name" => "bb"
      "value" => 22
    ]
  ]
  33 => array:3 [▼
    0 => array:2 [▼
      "name" => "bb"
      "value" => 33
    ]
    1 => array:2 [▼
      "name" => "bb"
      "value" => 33
    ]
    2 => array:2 [▼
      "name" => "bb"
      "value" => 33
    ]
  ]
]
Suburbanite answered 11/5, 2018 at 9:8 Comment(1)
Great example, thank you so much!Chorister
S
8

You could try something like:

$collection->groupBy('article_id')->flatMap(function ($items) {

    $quantity = $items->sum('quantity');

    return $items->map(function ($item) use ($quantity) {

        $item->quantity = $quantity;

        return $item;

    });

});

Obviously, change $collection to be whatever you've called the variable that holds your collection.

Hope this helps!

Straus answered 30/11, 2016 at 13:43 Comment(0)
B
2

Looks like the best way is:

$collectionA = collect(..some articles)->pluck('article_id');
$collectionB = collect(..another articles)->pluck('article_id');

$duplicates = $collectionA->merge($collectionB)->duplicates();
Bertolde answered 6/12, 2022 at 12:34 Comment(0)
P
0
$datas = ($datas)->map(function ($data) use ($datas) {
        $sum = $datas->where('article_id', $data['article_id'])->sum('quantity');
        $data['quantity'] = $sum;
        return $data;
    })->toArray();
Progestational answered 23/3, 2023 at 8:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.