Skip to content

Commit

Permalink
refactor: update sort operation
Browse files Browse the repository at this point in the history
Use `SortIterator` from `loophp/iterators` now.
  • Loading branch information
drupol committed Sep 29, 2023
1 parent 5321ebc commit cc26a56
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 53 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
],
"require": {
"php": ">= 8.1",
"loophp/iterators": "^2.3.5"
"loophp/iterators": "^2.4"
},
"require-dev": {
"ext-pcov": "*",
Expand Down
110 changes: 58 additions & 52 deletions src/Operation/Sort.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

namespace loophp\collection\Operation;

use ArrayIterator;
use Closure;
use Exception;
use Generator;
use loophp\collection\Contract\Operation;
use loophp\iterators\SortIterator;

/**
* @immutable
Expand All @@ -28,61 +28,67 @@ public function __invoke(): Closure
* @return Closure(null|(callable(T|TKey, T|TKey): int)): Closure(iterable<TKey, T>): Generator<TKey, T>
*/
static fn (int $type = Operation\Sortable::BY_VALUES): Closure =>
/**
* @param null|(callable(T|TKey, T|TKey): int) $callback
*
* @return Closure(iterable<TKey, T>): Generator<TKey, T>
*/
static function (?callable $callback = null) use ($type): Closure {
$callback ??=
/**
* @param T|TKey $left
* @param T|TKey $right
*/
static fn (mixed $left, mixed $right): int => $left <=> $right;

return
/**
* @param iterable<TKey, T> $iterable
*
* @return Generator<TKey, T>
*/
static function (iterable $iterable) use ($type, $callback): Generator {
if (Operation\Sortable::BY_VALUES !== $type && Operation\Sortable::BY_KEYS !== $type) {
throw new Exception('Invalid sort type.');
}
/**
* @param null|(callable(T|TKey, T|TKey): int) $callback
*
* @return Closure(iterable<TKey, T>): Generator<TKey, T>
*/
static function (?callable $callback = null) use ($type): Closure {
$callback ??=
/**
* @param T|TKey $left
* @param T|TKey $right
*/
static fn (mixed $left, mixed $right): int => $left <=> $right;

$operations = Operation\Sortable::BY_VALUES === $type ?
[
'before' => [(new Pack())()],
'after' => [(new Unpack())()],
] :
[
'before' => [(new Flip())(), (new Pack())()],
'after' => [(new Unpack())(), (new Flip())()],
];
return
/**
* @param iterable<TKey, T> $iterable
*
* @return Generator<TKey, T>
*/
static function (iterable $iterable) use ($type, $callback): Generator {
if (Operation\Sortable::BY_VALUES !== $type && Operation\Sortable::BY_KEYS !== $type) {
throw new Exception('Invalid sort type.');
}

$sortCallback =
/**
* @param callable(T|TKey, T|TKey): int $callback
*
* @return Closure(array{0:TKey|T, 1:T|TKey}, array{0:TKey|T, 1:T|TKey}): int
*/
static fn (callable $callback): Closure =>
/**
* @param array{0:TKey|T, 1:T|TKey} $left
* @param array{0:TKey|T, 1:T|TKey} $right
*/
static fn (array $left, array $right): int => $callback($left[1], $right[1]);
$operations = Operation\Sortable::BY_VALUES === $type ?
[
'before' => [(new Pack())()],
'after' => [(new Unpack())()],
] :
[
'before' => [(new Flip())(), (new Pack())()],
'after' => [(new Unpack())(), (new Flip())()],
];

/** @var callable(iterable<TKey, T>): Generator<int, array{0:TKey, 1:T}> | callable(iterable<TKey, T>): Generator<int, array{0:T, 1:TKey}> $before */
$before = (new Pipe())()(...$operations['before']);
$sortCallback =
/**
* @param callable(T|TKey, T|TKey): int $callback
*
* @return Closure(array{0:TKey|T, 1:T|TKey}, array{0:TKey|T, 1:T|TKey}): int
*/
static fn (callable $callback): Closure =>
/**
* @param array{0:TKey|T, 1:T|TKey} $left
* @param array{0:TKey|T, 1:T|TKey} $right
*/
static fn (array $left, array $right): int => $callback($right[1], $left[1]);

$arrayIterator = new ArrayIterator([...$before($iterable)]);
$arrayIterator->uasort($sortCallback($callback));
$sortedIterator =
/**
* @param iterable<TKey, T> $iterable
*
* @return SortIterator<TKey, T>
*/
static fn (iterable $iterable): SortIterator => new SortIterator($iterable, $sortCallback($callback));

yield from (new Pipe())()(...$operations['after'])($arrayIterator);
};
};
yield from (new Pipe())()(
...$operations['before'],
...[$sortedIterator],
...$operations['after']
)($iterable);
};
};
}
}

0 comments on commit cc26a56

Please sign in to comment.