-
-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature request] Implement stable sorting #331
Comments
Hi! Thanks for bringing this here, I wasn't aware of that behavior. |
@jazithedev Let me know if the proposed PR fixes the issue ? |
@drupol In your test from PR you can use abstract classes to get rid of such classes like public function testIssue331(): void
{
$valueObjectFactory = static fn ($id, $weight) => new class($id, $weight) {
public function __construct(
public int $id,
public int $weight,
) {
}
};
$input = Collection::fromIterable([
$valueObjectFactory(id: 1, weight: 1),
$valueObjectFactory(id: 2, weight: 1),
$valueObjectFactory(id: 3, weight: 1),
])
->sort(callback: static fn ($a, $b): int => $a->weight <=> $b->weight)
->map(static fn ($item): int => $item->id);
self::assertEquals([1, 2, 3], $input->all());
} It is just a bit less readable probably. |
Thanks for this nice bug report! The fix will be available in 7.4. |
@jazithedev I improved further the sort operation, do you mind testing the development version? Related PR: #334 |
Sure! I'll check it tomorrow 👍️. |
Unfortunately, something is not right at
The PHP version passes, where the other unfortunately doesn't. private static function createValueObject(int $id, int $weight): object
{
return new class($id, $weight) {
public function __construct(
public int $id,
public int $weight,
) {
}
};
}
public function testPhpSorting(): void
{
$input = [
self::createValueObject(id: 1, weight: 2),
self::createValueObject(id: 160, weight: 1),
self::createValueObject(id: 1600, weight: 3),
self::createValueObject(id: 2, weight: 2),
self::createValueObject(id: 150, weight: 1),
self::createValueObject(id: 1500, weight: 3),
self::createValueObject(id: 3, weight: 2),
];
usort($input, static fn ($a, $b): int => $a->weight <=> $b->weight);
$collection = Collection::fromIterable($input)->map(static fn ($item): int => $item->id);
self::assertEquals([160, 150, 1, 2, 3, 1600, 1500], $collection->all());
}
public function testCollectionSorting(): void
{
$input = Collection::fromIterable([
self::createValueObject(id: 1, weight: 2),
self::createValueObject(id: 160, weight: 1),
self::createValueObject(id: 1600, weight: 3),
self::createValueObject(id: 2, weight: 2),
self::createValueObject(id: 150, weight: 1),
self::createValueObject(id: 1500, weight: 3),
self::createValueObject(id: 3, weight: 2),
])
->sort(callback: static fn ($a, $b): int => $a->weight <=> $b->weight)
->map(static fn ($item): int => $item->id);
self::assertEquals([160, 150, 1, 2, 3, 1600, 1500], $input->all());
} Both tests are fine with |
Thanks, looking at it immediately ! |
I see the issue. To preserve the old behaviour, I had to keep sorting in the same direction (ASC). To fix the issue you just posted, you just need to update your callback as such: ->sort(callback: static fn ($a, $b): int => $b->weight <=> $a->weight) And the test are passing. |
After giving a second thought, I'm going to update the behaviour in |
Indeed the change you suggested works. Tho, it's a bit strange 😅. I mean, I think in most cases of "spaceship operator" it is One another thing I noticed is keys preservation. The |
Everything has been fixed in 7.5.0 which is now available :) Thanks for this very interesting issue and the tests ! |
Hello 👋.
Let's assume to have this simple value object in the project:
I need a feature of sorting such value objects by weight. The major thing about it is that the sorting itself must be stable. Meaning, two objects of the same weight should not exchange their position with each other within a single list. This can be tested with such a test:
Unfortunately, the test fails as the result stored in the
$input
variable is[1, 3, 2]
. Meaning: sorting is not stable.Such thing was already addressed in the past for PHP. On 2022 Nikita Popov made PHP sorting stable. Hence, using
usort(...)
function in the above example will make the test to pass.Would it be possible to implement stable sorting in loophp/collection?
The text was updated successfully, but these errors were encountered: