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;
    }