Skip to content

Commit

Permalink
feat: implements stable sorting
Browse files Browse the repository at this point in the history
Fix #331
  • Loading branch information
drupol committed Jan 15, 2024
1 parent 71a6145 commit bfe6a55
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 1 deletion.
3 changes: 3 additions & 0 deletions docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2140,6 +2140,9 @@ Sort a collection using a callback. If no callback is provided, it will sort usi
By default, it will sort by values and using a callback. If you want to sort by keys, you can pass a parameter to change
the behaviour or use twice the flip operation. See the example below.

Since version 7.4, sorting is `stable` by default. Stable sort algorithms sort equal
elements in the same order that they appear in the input.

Interface: `Sortable`_

Signature: ``Collection::sort(int $type = Sortable::BY_VALUES, ?callable $callback = null): Collection;``
Expand Down
2 changes: 1 addition & 1 deletion src/Operation/Sort.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static function (iterable $iterable) use ($type, $callback): Generator {
* @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]);
static fn (array $left, array $right): int => (0 === $return = $callback($right[1], $left[1])) ? ($right[0] <=> $left[0]) : $return;

$sortedIterator =
/**
Expand Down
20 changes: 20 additions & 0 deletions tests/unit/IssuesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,24 @@ public function testIssue264()
self::assertEquals('c', $subject->get(300));
self::assertEquals('d', $subject->get(400));
}

public function testIssue331(): void
{
$valueObjectFactory = static fn (int $id, int $weight) => new class($id, $weight) {
public function __construct(
public readonly int $id,
public readonly int $weight,
) {}
};

$input = Collection::fromIterable([
$valueObjectFactory(id: 1, weight: 1),
$valueObjectFactory(id: 2, weight: 1),
$valueObjectFactory(id: 3, weight: 1),
])
->sort(callback: static fn (object $a, object $b): int => $a->weight <=> $b->weight)
->map(static fn ($item): int => $item->id);

self::assertEquals([1, 2, 3], $input->all());
}
}

0 comments on commit bfe6a55

Please sign in to comment.