Skip to content
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

Sort the results of PriorityQueue::toArray() according to priority #109

Merged
merged 3 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/book/v4/migration/v3-to-v4.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ All classes have been updated to make use of parameter and return types. In gene

The addition of property, parameter and return types will cause fatal errors for extending classes that re-define those properties or override changed methods. If you have extended from any classes in laminas-stdlib, you should check that property types and method signatures are compatible and update them if they are not aligned.

### `PriorityQueue::toArray()` Now Returns Data in Order of Priority

In previous versions, `PriorityQueue::toArray()` returned data in insertion order. This method now returns data in priority order making it effectively the same as `iterator_to_array($queue)`, with the exception that you can pass extraction flags to `PriorityQueue::toArray()`.

## Removed Features

None.
Expand Down
23 changes: 16 additions & 7 deletions src/PriorityQueue.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use function serialize;
use function sprintf;
use function unserialize;
use function usort;

/**
* Re-usable, serializable priority queue implementation
Expand Down Expand Up @@ -245,13 +246,12 @@ public function __unserialize(array $data): void
}

/**
* Serialize to an array
* By default, returns only the item data, and in the order registered (not
* sorted). You may provide one of the EXTR_* flags as an argument, allowing
* Serialize to an array, ordered by priority
* By default, returns only the item data. You may provide one of the EXTR_* flags as an argument, allowing
* the ability to return priorities or both data and priority.
*
* @param self::EXTR_* $flag
* @return array<array-key, mixed>
* @return list<mixed>
* @psalm-return ($flag is self::EXTR_BOTH
* ? list<array{data: TValue, priority: int}>
* : $flag is self::EXTR_PRIORITY
Expand All @@ -261,10 +261,19 @@ public function __unserialize(array $data): void
*/
public function toArray(int $flag = self::EXTR_DATA): array
{
/**
* A manual sort is required because $item['priority'] as stored in the inner queue could be an array as
* opposed to an integer.
*/
$items = $this->items;
usort($items, function (array $a, array $b): int {
return $b['priority'] <=> $a['priority'];
});

return match ($flag) {
self::EXTR_BOTH => $this->items,
self::EXTR_PRIORITY => array_map(static fn($item): int => $item['priority'], $this->items),
default => array_map(static fn($item): mixed => $item['data'], $this->items),
self::EXTR_BOTH => $items,
self::EXTR_PRIORITY => array_map(static fn($item): int => $item['priority'], $items),
default => array_map(static fn($item): mixed => $item['data'], $items),
};
}

Expand Down
6 changes: 3 additions & 3 deletions test/PriorityQueueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public function testSerializationAndDeserializationShouldMaintainState(): void
public function testRetrievingQueueAsArrayReturnsDataOnlyByDefault(): void
{
$expected = [
'foo',
'bar',
'foo',
'baz',
'bat',
];
Expand All @@ -68,8 +68,8 @@ public function testRetrievingQueueAsArrayReturnsDataOnlyByDefault(): void
public function testCanCastToArrayOfPrioritiesOnly(): void
{
$expected = [
3,
4,
3,
2,
1,
];
Expand All @@ -80,8 +80,8 @@ public function testCanCastToArrayOfPrioritiesOnly(): void
public function testCanCastToArrayOfDataPriorityPairs(): void
{
$expected = [
['data' => 'foo', 'priority' => 3],
['data' => 'bar', 'priority' => 4],
['data' => 'foo', 'priority' => 3],
['data' => 'baz', 'priority' => 2],
['data' => 'bat', 'priority' => 1],
];
Expand Down