document enum ordering of native sorts

This commit is contained in:
Kacper Donat 2026-10-28 10:05:33 +01:00
parent b2550cf80b
commit 4ad971b431
3 changed files with 23 additions and 5 deletions

View File

@ -268,9 +268,10 @@ A few consequences worth knowing:
- `merge()` merges arrays and `Ds\Map` by key (integer keys of arrays are kept, unlike `array_merge()`); for other - `merge()` merges arrays and `Ds\Map` by key (integer keys of arrays are kept, unlike `array_merge()`); for other
inputs it appends. inputs it appends.
- `sort()`/`sortBy()` are stable and never modify their input, unlike `Ds\Seq::sort()`. - `sort()`/`sortBy()` are stable and never modify their input, unlike `Ds\Seq::sort()`.
- `sort()` without a comparator and `sortBy()` sort natively, comparing like `<=>`. The one difference is enums, - `sort()` without a comparator and `sortBy()` sort natively, comparing like `<=>`. The one difference is enums
which `<=>` can't order: they are grouped by case and placed after the other values (before them in descending used directly as the sort key (or as the values for `sort()`), which `<=>` can't order: they are grouped by case,
order). in an unspecified order (PHP compares object addresses, not declaration order), and placed after the other values
(before them in descending order). Enums nested inside arrays compare as `<=>` does.
### Finding things: `first`, `find` and `required` ### Finding things: `first`, `find` and `required`

View File

@ -310,7 +310,8 @@ function uniqueBy(callable $selector): \Closure
/** /**
* Sorts the values with `$comparator($a, $b)` (an int like `<=>`), or with `<=>` when it is null. * Sorts the values with `$comparator($a, $b)` (an int like `<=>`), or with `<=>` when it is null.
* *
* The sort is stable and keeps the keys of arrays and `Ds\Map`. The input is never modified. * The sort is stable and keeps the keys of arrays and `Ds\Map`. The input is never modified. Without a comparator,
* enums are ordered differently from `<=>` (see "What you get back" in the README).
* *
* @template TValue = mixed * @template TValue = mixed
* *
@ -372,7 +373,8 @@ function sort(?callable $comparator = null): \Closure
* Sorts the values by `$selector($value, $key)`, compared with `<=>`, in ascending or descending order. * Sorts the values by `$selector($value, $key)`, compared with `<=>`, in ascending or descending order.
* *
* The sort is stable (equal values keep their order in both directions) and keeps the keys of arrays and * The sort is stable (equal values keep their order in both directions) and keeps the keys of arrays and
* `Ds\Map`. The selector is called once per value. The input is never modified. * `Ds\Map`. The selector is called once per value. The input is never modified. Enum keys are ordered differently
* from `<=>` (see "What you get back" in the README).
* *
* @template TKey = mixed * @template TKey = mixed
* @template TValue = mixed * @template TValue = mixed

View File

@ -349,6 +349,21 @@ class TransformsTest extends \PHPUnit\Framework\TestCase
$this->assertSame([1, 2], $sorted->values()->toArray()); $this->assertSame([1, 2], $sorted->values()->toArray());
} }
public function testSortWithComparatorKeepsObjectKeysOfMap()
{
$a = new \stdClass();
$b = new \stdClass();
$map = new Map();
$map->put($a, 1);
$map->put($b, 2);
$sorted = c\sort(fn ($x, $y) => $y <=> $x)($map);
$this->assertInstanceOf(Map::class, $sorted);
$this->assertSame([$b, $a], $sorted->keys()->toArray());
$this->assertSame([2, 1], $sorted->values()->toArray());
}
public function testSortByDoesNotMutateInput() public function testSortByDoesNotMutateInput()
{ {
$array = ['x' => 3, 'y' => 1, 'z' => 2]; $array = ['x' => 3, 'y' => 1, 'z' => 2];