diff --git a/src/Collections/IComparable.php b/src/Collections/IComparable.php new file mode 100644 index 0000000..33ba7b8 --- /dev/null +++ b/src/Collections/IComparable.php @@ -0,0 +1,23 @@ +< 0 if current instance is classed before the other instance + *
= 0 if current instance is classed equals the other instance + *
> 0 if current instance is classed after the other instance + * + * @noinspection PhpMissingParamTypeInspection + */ + public function compareTo ($other): int; +} \ No newline at end of file diff --git a/src/Collections/IComparator.php b/src/Collections/IComparator.php new file mode 100644 index 0000000..c63e67e --- /dev/null +++ b/src/Collections/IComparator.php @@ -0,0 +1,24 @@ +< 0 if the first object is classed before the second object + *
= 0 if the first object is classed equals the second object + *
> 0 if the first object is classed after the second object + * + * @noinspection PhpMissingParamTypeInspection + */ + public function compare ($object1, $object2): int; +} \ No newline at end of file diff --git a/src/Collections/IImmutableCollection.php b/src/Collections/IImmutableCollection.php index 45a74ea..9c03f17 100644 --- a/src/Collections/IImmutableCollection.php +++ b/src/Collections/IImmutableCollection.php @@ -8,6 +8,7 @@ use Countable; use IteratorAggregate; use JsonSerializable; use Serializable; +use Throwable; /** * Interface for an immutable (read-only) collection @@ -126,6 +127,40 @@ interface IImmutableCollection extends IteratorAggregate, JsonSerializable, Seri */ public function map (Closure $process): self; + /** + * Sort the elements (by value) + * + * @param null|IComparator|Closure(TValue, TValue):int $sorter The sorting method ; Null if values are object implementing {@see IComparable}. + *
Return : + *
< 0 if value1 is before value2 + *
= 0 if value1 equals value2 + *
> 0 if value1 is after value2 + * + * @return static The sorted collection + * @psalm-return static + * + * @throws Throwable If an error occurs + * + * @noinspection PhpMissingReturnTypeInspection + */ + public function sort ($sorter = null); + /** + * Sort the elements by key + * + * @param IComparator|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 static The sorted collection + * @psalm-return static + * + * @throws Throwable If an error occurs + * + * @noinspection PhpMissingReturnTypeInspection + */ + public function sortByKey ($sorter); + /** * The list of all keys * diff --git a/src/Collections/ImmutableCollection.php b/src/Collections/ImmutableCollection.php index e358d87..74d636d 100644 --- a/src/Collections/ImmutableCollection.php +++ b/src/Collections/ImmutableCollection.php @@ -294,6 +294,42 @@ class ImmutableCollection implements IImmutableCollection { return $output; } + /** + * @inheritDoc + */ + public function sort ($sorter = null) { + if ($sorter === null) { + $sorter = function (IComparable $value1, IComparable $value2): int { + return $value1->compareTo($value2); + }; + } + elseif ($sorter instanceof IComparator) { + $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 ($sorter) { + if ($sorter instanceof IComparator) { + $sorter = function ($value1, $value2) use ($sorter): int { + return $sorter->compare($value1, $value2); + }; + } + + $elements = $this->toArray(); + uksort($elements, $sorter); + + return new static($elements); + } + /** * @inheritDoc */ diff --git a/tests/test_class.php b/tests/test_class.php index 77cbd71..837f4db 100644 --- a/tests/test_class.php +++ b/tests/test_class.php @@ -1,11 +1,19 @@ + */ +class Measure implements IComparable { private int $value; private string $unit; @@ -14,9 +22,33 @@ class Measure { $this->unit = $unit; } + public function getValue (): int { + return $this->value; + } + public function asString (): string { return $this->value . $this->unit; } + + /** + * @inheritDoc + */ + public function compareTo ($other): int { + return $this->value <=> $other->value; + } +} +/** + * Class MeasureReverseComparator + * + * @implements IComparator + */ +class MeasureReverseComparator implements IComparator { + /** + * @inheritDoc + */ + public function compare ($object1, $object2): int { + return -($object1->getValue() <=> $object2->getValue()); + } } /** @@ -34,6 +66,11 @@ function getMeasures (): Collection { } echo 'Measures :' . PHP_EOL; -foreach (getMeasures() as $no => $measure) { +foreach (getMeasures()->sort() as $no => $measure) { + echo "\t#" . $no . ' = ' . $measure->asString() . PHP_EOL; +} + +echo 'Measures (reversed) :' . PHP_EOL; +foreach (getMeasures()->sort(new MeasureReverseComparator()) as $no => $measure) { echo "\t#" . $no . ' = ' . $measure->asString() . PHP_EOL; } \ No newline at end of file