Switch to self implemented IComparable and IComparator

2.x 2.5.0
Julien Rosset 2 years ago
parent d293b3fe7b
commit a603f32fd6

@ -0,0 +1,23 @@
<?php
namespace jrosset\Collections;
/**
* Interface for comparable objects
*
* @template TObject of object
*/
interface IComparable {
/**
* Compare to another instance
*
* @param TObject $other The other instance
*
* @return int <br>&lt; 0 if current instance is classed before the other instance
* <br>= 0 if current instance is classed equals the other instance
* <br>&gt; 0 if current instance is classed after the other instance
*
* @noinspection PhpMissingParamTypeInspection
*/
public function compareTo ($other): int;
}

@ -0,0 +1,24 @@
<?php
namespace jrosset\Collections;
/**
* Interface for classes comparing external objects
*
* @template TObject of object
*/
interface IComparator {
/**
* Compare two objects
*
* @param TObject $object1 The first object
* @param TObject $object2 The second object
*
* @return int <br>&lt; 0 if the first object is classed before the second object
* <br>= 0 if the first object is classed equals the second object
* <br>&gt; 0 if the first object is classed after the second object
*
* @noinspection PhpMissingParamTypeInspection
*/
public function compare ($object1, $object2): int;
}

@ -8,6 +8,7 @@ use Countable;
use IteratorAggregate; use IteratorAggregate;
use JsonSerializable; use JsonSerializable;
use Serializable; use Serializable;
use Throwable;
/** /**
* Interface for an immutable (read-only) collection * Interface for an immutable (read-only) collection
@ -126,6 +127,40 @@ interface IImmutableCollection extends IteratorAggregate, JsonSerializable, Seri
*/ */
public function map (Closure $process): self; 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}.
* <br>Return :
* <br>&lt; 0 if value1 is before value2
* <br>= 0 if value1 equals value2
* <br>&gt; 0 if value1 is after value2
*
* @return static The sorted collection
* @psalm-return static<TKey, TValue>
*
* @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 :
* <br>&lt; 0 if key1 is before key2
* <br>= 0 if key1 equals key2
* <br>&gt; 0 if key1 is after key2
*
* @return static The sorted collection
* @psalm-return static<TKey, TValue>
*
* @throws Throwable If an error occurs
*
* @noinspection PhpMissingReturnTypeInspection
*/
public function sortByKey ($sorter);
/** /**
* The list of all keys * The list of all keys
* *

@ -294,6 +294,42 @@ class ImmutableCollection implements IImmutableCollection {
return $output; 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 * @inheritDoc
*/ */

@ -1,11 +1,19 @@
<?php <?php
/** @noinspection PhpUnhandledExceptionInspection */
/** @noinspection PhpIllegalPsrClassPathInspection */ /** @noinspection PhpIllegalPsrClassPathInspection */
use jrosset\Collections\Collection; use jrosset\Collections\Collection;
use jrosset\Collections\IComparable;
use jrosset\Collections\IComparator;
require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../vendor/autoload.php';
class Measure { /**
* Class Measure
*
* @implements IComparable<static>
*/
class Measure implements IComparable {
private int $value; private int $value;
private string $unit; private string $unit;
@ -14,9 +22,33 @@ class Measure {
$this->unit = $unit; $this->unit = $unit;
} }
public function getValue (): int {
return $this->value;
}
public function asString (): string { public function asString (): string {
return $this->value . $this->unit; return $this->value . $this->unit;
} }
/**
* @inheritDoc
*/
public function compareTo ($other): int {
return $this->value <=> $other->value;
}
}
/**
* Class MeasureReverseComparator
*
* @implements IComparator<Measure>
*/
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; 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; echo "\t#" . $no . ' = ' . $measure->asString() . PHP_EOL;
} }
Loading…
Cancel
Save