src/Utils/Utils.php
public static function groupBy($traversable, callable $keyFn)
    {
        self::invariant(
            is_array($traversable) || $traversable instanceof Traversable,
            __METHOD__ . ' expects array or Traversable'
        );

        $grouped = [];
        foreach ($traversable as $key => $value) {
            $newKeys = (array) $keyFn($value, $key);
            foreach ($newKeys as $newKey) {
                $grouped[$newKey][] = $value;
            }
        }

        return $grouped;
    }
public static function groupBy($traversable, callable $keyFn)
    {
        self::invariant(
            is_array($traversable) || $traversable instanceof Traversable,
            __METHOD__ . ' expects array or Traversable'
        );

        $grouped = [];
        foreach ($traversable as $key => $value) {
            $newKeys = (array) $keyFn($value, $key);
            foreach ($newKeys as $newKey) {
                $grouped[$newKey][] = $value;
            }
        }

        return $grouped;
    }
public static function groupBy ( $ traversable , callable $ keyFn ) { self :: invariant ( is_array ( $ traversable ) || $ traversable instanceof Traversable , __METHOD__ . ' expects array or Traversable' ) ; $ grouped = [ ] ; foreach ( $ traversable as $ key => $ value ) { $ newKeys = ( array ) $ keyFn ( $ value , $ key ) ; foreach ( $ newKeys as $ newKey ) { $ grouped [ $ newKey ] [ ] = $ value ; } } return $ grouped ; }
Splits original traversable to several arrays with keys equal to $keyFn return

E.g. Utils::groupBy([1, 2, 3, 4, 5], function($value) {return $value % 3}) will output:
[
1 => [1, 4],
2 => [2, 5],
0 => [3],
]

$keyFn is also allowed to return array of keys. Then value will be added to all arrays with given keys

@param mixed[]|Traversable $traversable

@return mixed[]
Splits original traversable to several arrays with keys equal to $keyFn return