code: 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;
      }
docs: 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