Skip to content

Commit

Permalink
fix: sort direction match usort
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Jan 22, 2024
1 parent c63365d commit e6d42d9
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 27 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ This means that if two elements have the same key, the one that appeared earlier
in the input will also appear earlier in the sorted output.

```php
$valueObjectFactory = static fn (int $id, int $weight) => new class($id, $weight)
$valueObjectFactory = static fn (int $id, int $weight): object => new class($id, $weight)
{
public function __construct(public readonly int $id, public readonly int $weight) {}
};
Expand Down
2 changes: 1 addition & 1 deletion src/SortIterableAggregate.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function __construct(iterable $iterable, private Closure $callback)
*/
protected function compare($value1, $value2): int
{
return (0 === $return = ($this->callback)($value1[1][1], $value2[1][1], $value1[1][0], $value2[1][0])) ? $value2[0] <=> $value1[0] : $return;
return (0 === $return = ($this->callback)($value2[1][1], $value1[1][1], $value2[1][0], $value1[1][0])) ? $value2[0] <=> $value1[0] : $return;
}
};

Expand Down
79 changes: 54 additions & 25 deletions tests/unit/SortIterableAggregateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,53 +22,82 @@ final class SortIterableAggregateTest extends TestCase
{
public function testDoNothing(): void
{
$input = ['a', 'b', 'c', 'd', 'e', 'f'];
$input = range('a', 'f');

$iterator = (new SortIterableAggregate($input, static fn ($right, $left): int => $left <=> $right));
$iterator = (new SortIterableAggregate($input, static fn (string $left, string $right): int => $left <=> $right));

$expected = [];
$actual = array_reduce(
iterator_to_array($iterator),
static fn (array $carry, string $item): array => [...$carry, $item],
[]
);

foreach ($iterator as $value) {
$expected[] = $value;
}

self::assertSame($expected, $input);
self::assertSame($input, $actual);
}

public function testSimpleSort(): void
{
$input = array_combine(range('c', 'a'), range('c', 'a'));

$iterator = (new SortIterableAggregate($input, static fn ($right, $left): int => $left <=> $right));
$iterator = (new SortIterableAggregate($input, static fn (string $left, string $right): int => $left <=> $right));

$actual = array_reduce(
iterator_to_array($iterator),
static fn (array $carry, string $item): array => [...$carry, $item],
[]
);

self::assertSame(range('a', 'c'), $actual);
}

public function testSortingDirectionMatchUsort(): 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),
];

$expected = [];
$sortCallback = static fn (object $a, object $b): int => $a->weight <=> $b->weight;

foreach ($iterator as $value) {
$expected[] = $value;
}
$actual = array_reduce(
iterator_to_array(new SortIterableAggregate($input, $sortCallback)),
static fn (array $carry, object $item): array => [...$carry, $item->id],
[]
);

self::assertSame($expected, range('a', 'c'));
usort($input, $sortCallback);
$expected = array_map(static fn (object $item): int => $item->id, $input);

self::assertEquals($expected, $actual);
}

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

$input = [
$valueObjectFactory(id: 1, weight: 1),
$valueObjectFactory(id: 2, weight: 1),
$valueObjectFactory(id: 3, weight: 1),
self::createValueObject(id: 1, weight: 1),
self::createValueObject(id: 2, weight: 1),
self::createValueObject(id: 3, weight: 1),
];

$sort = new SortIterableAggregate($input, static fn (object $a, object $b): int => $a->weight <=> $b->weight);

$expected = [1, 2, 3];
$expected = range(1, 3);

self::assertSame($expected, iterator_to_array(new MapIterableAggregate($sort, static fn (object $value): int => $value->id)));
}

private static function createValueObject(int $id, int $weight): object
{
return new class($id, $weight) {
public function __construct(
public int $id,
public int $weight,
) {}
};
}
}

0 comments on commit e6d42d9

Please sign in to comment.