PHP Group array by key or callback

1st June, 2016

Have you ever needed to group an array of data in PHP and had to write awkward loops or array_reduce code to accomplish this?

I've created a small package (just one function actually) and published it on Packagist.com so you can conveniently install it into your PHP applications with Composer.

composer install group-by/group-by

It adds a grouping functionality to arrays, allowing you to group by passing each item in the array to a callback.

Here's how you might want to use it:

<?php

use function GroupBy\groupBy;

// $students in an array of `stdClass Object`
$students = [
    (object) ['name' => 'adam', 'year' => '10'],
    (object) ['name' => 'becky', 'year' => '12'],
    (object) ['name' => 'chris', 'year' => '11'],
    (object) ['name' => 'deborah', 'year' => '10'],
    (object) ['name' => 'edward', 'year' => '12'],
];

$groupByYear = function ($student) {
    return $student->year;
};

$groupedByYear = groupBy($students, $groupByYear);

/*
$groupedByYear is now equal to
[
    [10] => [
        [0] => stdClass Object
            (
                [name] => adam
                [year] => 10
            )
        [1] => stdClass Object
            (
                [name] => deborah
                [year] => 10
            )
        ]
    [12] => [
        [0] => stdClass Object
            (
                [name] => becky
                [year] => 12
            )
        [1] => stdClass Object
            (
                [name] => edward
                [year] => 12
            )
        ]
    [11] => [
        [0] => stdClass Object
            (
                [name] => chris
                [year] => 11
            )
    ]
]
*/

You could also group an array of arrays, like so:

<?php

use function GroupBy\groupBy;

$numberList = [1, 2, 3, 4, 5, 987, 554, 32];

// The array item value will be passed to the callback.
$oddOrEven = function ($n) {
    return $n % 2 == 0 ? 'even' : 'odd';
};

$oddAndEven = groupBy($numberList, $oddOrEven);

/*
$oddAndEven is now equal to
[
    'odd' => [1, 3, 5, 987],
    'even' => [2, 4, 554, 32],
];
*/

If you are grouping a group of arrays by a sub array key, you can just pass the string value of that key, like so:

<?php

use function GroupBy\groupBy;

$students = [
    ['name' => 'adam', 'year' => '10'],
    ['name' => 'becky', 'year' => '12'],
    ['name' => 'chris', 'year' => '11'],
    ['name' => 'deborah', 'year' => '10'],
    ['name' => 'edward', 'year' => '12'],
];

$groupedByYear = groupBy($students, 'year');

/*
$groupedByYear is equal to
[
    10 => [
        ['name' => 'adam', 'year' => '10'],
        ['name' => 'deborah', 'year' => '10'],
    ],
    11 => [
        ['name' => 'chris', 'year' => '11'],
    ],
    12 => [
        ['name' => 'becky', 'year' => '12'],
        ['name' => 'edward', 'year' => '12'],
    ],
]
*/

I have been using Haskell and Scala more recently and have found these groupBy methods very useful. I'm surprised I couldn't find a simple way to do this in PHP, so hopefully this will be useful to other people too.

Let me know if you like it or have any suggestions to improve it.

Further reading

Category: kata

Tagged: kata haskell js tdd