src/ArrayObject.php
public function groupBy($func)
    {
        $ret = array();
        $it  = $this->getIterator();

        while ($it->valid()) {

            if (is_object($it->current())) {
                $key = call_user_func($func, $it->current());
            } else {
                // Pass scalar values by reference, too
                $value = $it->current();
                $key = call_user_func_array($func, array(&$value));
                $it->offsetSet($it->key(), $value);
                unset($value);
            }

            if (is_array($key)) {
                $ref = &$ret;

                foreach ($key as $subkey) {
                    if (!array_key_exists($subkey, $ref)) {
                        $ref[$subkey] = array();
                    }
                    $ref = &$ref[$subkey];
                }
                $ref[] = $it->current();
            } else {
                $ret[$key][] = $it->current();
            }

            $it->next();
        }
        unset($ref);

        $ret = new self($ret);
        $this->exchangeArray($ret->getArrayCopy());

        return $this;
    }
public function groupBy($func)
    {
        $ret = array();
        $it  = $this->getIterator();

        while ($it->valid()) {

            if (is_object($it->current())) {
                $key = call_user_func($func, $it->current());
            } else {
                // Pass scalar values by reference, too
                $value = $it->current();
                $key = call_user_func_array($func, array(&$value));
                $it->offsetSet($it->key(), $value);
                unset($value);
            }

            if (is_array($key)) {
                $ref = &$ret;

                foreach ($key as $subkey) {
                    if (!array_key_exists($subkey, $ref)) {
                        $ref[$subkey] = array();
                    }
                    $ref = &$ref[$subkey];
                }
                $ref[] = $it->current();
            } else {
                $ret[$key][] = $it->current();
            }

            $it->next();
        }
        unset($ref);

        $ret = new self($ret);
        $this->exchangeArray($ret->getArrayCopy());

        return $this;
    }
Groups the array by one or more criteria defined via callback function

Each element in the first dimension of the array is passed to the
specified callback function and will be reordered in regard to the
returned value. This can either be a string with the new key or an array
with a stack of new keys. For an element <var>$e</var>, the callback
return value <var>array('a', 'b')</var> translates to
<var>$newArray['a']['b'][] = $e;</var>.

Callback functions may take the element argument by reference and modify
it during execution (e. g. to remove any fields that will be grouped by).

@param  callback $func Function to group by
@return ArrayObject Provides fluent interface