| @@ 11-64 (lines=54) @@ | ||
| 8 | use Zicht\Itertools\conversions; |
|
| 9 | use Zicht\Itertools\lib\GroupbyIterator; |
|
| 10 | ||
| 11 | trait GroupByTrait |
|
| 12 | { |
|
| 13 | /** |
|
| 14 | * Make an iterator that returns consecutive groups from this |
|
| 15 | * iterable. Generally, this iterable needs to already be sorted on |
|
| 16 | * the same key function. |
|
| 17 | * |
|
| 18 | * When $strategy is a string, the key is obtained through one of |
|
| 19 | * the following: |
|
| 20 | * 1. $value->{$strategy}, when $value is an object and |
|
| 21 | * $strategy is an existing property, |
|
| 22 | * 2. call $value->{$strategy}(), when $value is an object and |
|
| 23 | * $strategy is an existing method, |
|
| 24 | * 3. $value[$strategy], when $value is an array and $strategy |
|
| 25 | * is an existing key, |
|
| 26 | * 4. otherwise the key will default to null. |
|
| 27 | * |
|
| 28 | * Alternatively $strategy can be a closure. In this case the |
|
| 29 | * $strategy closure is called with each value in this iterable and the |
|
| 30 | * key will be its return value. $strategy is called with two |
|
| 31 | * parameters: the value and the key of the iterable as the first and |
|
| 32 | * second parameter, respectively. |
|
| 33 | * |
|
| 34 | * The operation of groupBy() is similar to the uniq filter in Unix. |
|
| 35 | * It generates a break or new group every time the value of the key |
|
| 36 | * function changes (which is why it is usually necessary to have |
|
| 37 | * sorted the data using the same key function). That behavior |
|
| 38 | * differs from SQL's GROUP BY which aggregates common elements |
|
| 39 | * regardless of their input order. |
|
| 40 | * |
|
| 41 | * > $list = [['type'=>'A', 'title'=>'one'], ['type'=>'A', 'title'=>'two'], ['type'=>'B', 'title'=>'three']] |
|
| 42 | * > iter\iterable($list)->groupBy('type') |
|
| 43 | * 'A'=>[['type'=>'A', 'title'=>'one'], ['type'=>'A', 'title'=>'two']] 'B'=>[['type'=>'B', 'title'=>'three']] |
|
| 44 | * |
|
| 45 | * @param null|string|\Closure $strategy |
|
| 46 | * @param bool $sort |
|
| 47 | * @return GroupbyIterator |
|
| 48 | */ |
|
| 49 | public function groupBy($strategy, $sort = true) |
|
| 50 | { |
|
| 51 | if (!is_bool($sort)) { |
|
| 52 | throw new \InvalidArgumentException('Argument $sort must be a boolean'); |
|
| 53 | } |
|
| 54 | ||
| 55 | if ($this instanceof \Iterator) { |
|
| 56 | return new GroupbyIterator( |
|
| 57 | conversions\mixed_to_value_getter($strategy), |
|
| 58 | $sort ? $this->sorted($strategy) : $this |
|
| 59 | ); |
|
| 60 | } |
|
| 61 | ||
| 62 | return null; |
|
| 63 | } |
|
| 64 | } |
|
| 65 | ||
| @@ 11-54 (lines=44) @@ | ||
| 8 | use Zicht\Itertools\conversions; |
|
| 9 | use Zicht\Itertools\lib\SortedIterator; |
|
| 10 | ||
| 11 | trait SortedTrait |
|
| 12 | { |
|
| 13 | /** |
|
| 14 | * Make an iterator that returns the values from this iterable |
|
| 15 | * sorted by $strategy |
|
| 16 | * |
|
| 17 | * When determining the order of two entries the $strategy is called |
|
| 18 | * twice, once for each value, and the results are used to determine |
|
| 19 | * the order. $strategy is called with two parameters: the value and |
|
| 20 | * the key of the iterable as the first and second parameter, respectively. |
|
| 21 | * |
|
| 22 | * When $reverse is true the order of the results are reversed. |
|
| 23 | * |
|
| 24 | * The sorted() function is guaranteed to be stable. A sort is stable |
|
| 25 | * if it guarantees not to change the relative order of elements that |
|
| 26 | * compare equal. this is helpful for sorting in multiple passes (for |
|
| 27 | * example, sort by department, then by salary grade). This also |
|
| 28 | * holds up when $reverse is true. |
|
| 29 | * |
|
| 30 | * > $list = [['type'=>'B', 'title'=>'second'], ['type'=>'C', 'title'=>'third'], ['type'=>'A', 'title'=>'first']] |
|
| 31 | * > iter\iterable($list)->sorted('type') |
|
| 32 | * ['type'=>'A', 'title'=>'first'] ['type'=>'B', 'title'=>'second']] ['type'=>'C', 'title'=>'third'] |
|
| 33 | * |
|
| 34 | * @param null|string|\Closure $strategy |
|
| 35 | * @param bool $reverse |
|
| 36 | * @return SortedIterator |
|
| 37 | */ |
|
| 38 | public function sorted($strategy = null, $reverse = false) |
|
| 39 | { |
|
| 40 | if (!is_bool($reverse)) { |
|
| 41 | throw new \InvalidArgumentException('Argument $reverse must be boolean'); |
|
| 42 | } |
|
| 43 | ||
| 44 | if ($this instanceof \Iterator) { |
|
| 45 | return new SortedIterator( |
|
| 46 | conversions\mixed_to_value_getter($strategy), |
|
| 47 | $this, |
|
| 48 | $reverse |
|
| 49 | ); |
|
| 50 | } |
|
| 51 | ||
| 52 | return null; |
|
| 53 | } |
|
| 54 | } |
|
| 55 | ||