From 593e118ba12573cf60e02306f503045f3553d38a Mon Sep 17 00:00:00 2001 From: Julien Rosset Date: Mon, 11 Sep 2023 12:05:33 +0200 Subject: [PATCH] Add methods to sort collections --- composer.json | 5 +-- src/Collections/IImmutableCollection.php | 33 ++++++++++++++++++- src/Collections/ImmutableCollection.php | 40 +++++++++++++++++++++++- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 812d691..37041ca 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,8 @@ "minimum-stability": "stable", "require": { - "php": "^8.1" + "php": "^8.1", + "sgh/comparable": "^1.1" }, "autoload": { "psr-4": { @@ -40,4 +41,4 @@ "docs": "https://git.jrosset.ovh/jrosset/PhpCollections/wiki", "source": "https://git.jrosset.ovh/jrosset/PhpCollections" } -} \ No newline at end of file +} diff --git a/src/Collections/IImmutableCollection.php b/src/Collections/IImmutableCollection.php index 6bc3bc6..a69571c 100644 --- a/src/Collections/IImmutableCollection.php +++ b/src/Collections/IImmutableCollection.php @@ -7,6 +7,9 @@ use Closure; use Countable; use IteratorAggregate; use JsonSerializable; +use SGH\Comparable\Comparable; +use SGH\Comparable\Comparator; +use Throwable; /** * Interface for an immutable (read-only) collection @@ -125,6 +128,34 @@ interface IImmutableCollection extends IteratorAggregate, JsonSerializable, Coun */ public function map (Closure $process): self; + /** + * Sort the elements (by value) + * + * @param null|Comparator|Closure(TValue, TValue):int $sorter The sorting method ; Null if values are object implementing {@see Comparable}. + *
Return : + *
< 0 if value1 is before value2 + *
= 0 if value1 equals value2 + *
> 0 if value1 is after value2 + * + * @return self The sorted collection + * + * @throws Throwable If an error occurs + */ + public function sort (Closure|Comparator|null $sorter = null): self; + /** + * Sort the elements by key + * + * @param Comparator|Closure(TKey, TKey):int $sorter The sorting method. Return : + *
< 0 if key1 is before key2 + *
= 0 if key1 equals key2 + *
> 0 if key1 is after key2 + * + * @return self The sorted collection + * + * @throws Throwable If an error occurs + */ + public function sortByKey (Closure|Comparator $sorter): self; + /** * The list of all keys * @@ -163,7 +194,7 @@ interface IImmutableCollection extends IteratorAggregate, JsonSerializable, Coun * * @param IImmutableCollection ...$collections The other collections to combine * - * @return static The combine collection + * @return static The combined collection */ public function combineWith (IImmutableCollection ...$collections): self; } \ No newline at end of file diff --git a/src/Collections/ImmutableCollection.php b/src/Collections/ImmutableCollection.php index f5f02e8..c89b247 100644 --- a/src/Collections/ImmutableCollection.php +++ b/src/Collections/ImmutableCollection.php @@ -5,6 +5,8 @@ namespace jrosset\Collections; use ArrayIterator; use Closure; use InvalidArgumentException; +use SGH\Comparable\Comparable; +use SGH\Comparable\Comparator; use Traversable; /** @@ -46,7 +48,7 @@ class ImmutableCollection implements IImmutableCollection { * @throws InvalidArgumentException If the initial values aren't valid * @internal */ - protected function _initialize (?iterable $other = null) { + protected function _initialize (?iterable $other = null): void { $this->elements = []; if ($other !== null) { if (!is_array($other) && !$other instanceof Traversable) { @@ -300,6 +302,42 @@ class ImmutableCollection implements IImmutableCollection { return $output; } + /** + * @inheritDoc + */ + public function sort (Closure|Comparator|null $sorter = null): static { + if ($sorter === null) { + $sorter = function (Comparable $value1, Comparable $value2): int { + return $value1->compareTo($value2); + }; + } + elseif ($sorter instanceof Comparator) { + $sorter = function ($value1, $value2) use ($sorter): int { + return $sorter->compare($value1, $value2); + }; + } + + $elements = $this->toArray(); + uasort($elements, $sorter); + + return new static($elements); + } + /** + * @inheritDoc + */ + public function sortByKey (Closure|Comparator $sorter): static { + if ($sorter instanceof Comparator) { + $sorter = function ($value1, $value2) use ($sorter): int { + return $sorter->compare($value1, $value2); + }; + } + + $elements = $this->toArray(); + uksort($elements, $sorter); + + return new static($elements); + } + /** * @inheritDoc */