Laravel 5 Collections: Reducing a Collection Into a Collection of Key/Collection-Value Pairs With mapToGroups

April 22, 2018 —John Koster

The mapToGroups method is similar to the mapToDictionary method, in that the mapToGroups method allows you take a collection of data and reduce it such that the final result is a collection of key/value pairs. The resulting value for each key may be a single value, or another collection of items. The difference between the mapToGroups and mapToDictionary methods is that, unlike the mapToDictionary method, the mapToGroups will create collections for each key's values (the mapToDictionary creates arrays for each key's values).

The mapToGroups method defines a single $callback parameter, the return value of the callback function should be an associative array describing the relationship of the dictionary's key and values.

The mapToGroups method does not modify the original array; the method returns a new collection with the dictionary structure.

#Signature

1public function mapToGroups(
2 callable $callback
3);

#Example Use

In the following example we will reuse the scores example from the mapToDictionary section:

1// Student test scores.
2$testScores = new Collection([
3 ['score' => 0.84, 'name' => 'Bob'],
4 ['score' => 0.95, 'name' => 'Alice'],
5 ['score' => 0.78, 'name' => 'Charlie'],
6 ['score' => 0.92, 'name' => 'Alice'],
7 ['score' => 0.98, 'name' => 'Bob'],
8]);

While we could sort the list of tests scores by the student name, it is still not the easiest to quickly view the test scores of one particular student; ideally, we would like to have one entry for each student with their associated test scores.

We can accomplish this using the mapToDictionary method like so:

1$scores = $testScores->mapToGroups(function ($item, $key) {
2 return [$item['name'] => $item['score']];
3});

In the previous example, the callback function returned an associative array describing the relationship between the student names and their test scores. After we have invoked the mapToGroups method, the $scores collection would contain three elements for each of the students; each student element would have a nested collection value containing their test scores:

1Collection {
2 #items: array [
3 "Bob" => Collection {
4 #items: array [
5 0 => 0.84
6 1 => 0.98
7 ]
8 }
9 "Alice" => Collection {
10 #items: array [
11 0 => 0.95
12 1 => 0.92
13 ]
14 }
15 "Charlie" => Collection {
16 #items: array [
17 0 => 0.78
18 ]
19 }
20 ]
21}

Some absolutely amazing
people

The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.