From c1f2558778a8be754d99895f8bd6ac7aa7208cf4 Mon Sep 17 00:00:00 2001 From: Kamil Kokot Date: Mon, 25 May 2020 11:02:07 +0200 Subject: [PATCH] Keep FIFO order in PriorityQueue --- spec/Suite/PriorityQueueSpec.php | 12 +++++++----- src/Suite/PriorityQueue.php | 20 ++++++++------------ 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/spec/Suite/PriorityQueueSpec.php b/spec/Suite/PriorityQueueSpec.php index 45093fa..ae3610a 100644 --- a/spec/Suite/PriorityQueueSpec.php +++ b/spec/Suite/PriorityQueueSpec.php @@ -25,18 +25,20 @@ function it_is_initializable(): void function it_keeps_fifo_order_for_elements_with_same_priority(): void { - $this->insert(['element' => 1]); $this->insert(['element' => 2]); + $this->insert(['element' => 1]); + $this->insert(['element' => 3]); - $this->getIterator()->shouldIterateAs([['element' => 1], ['element' => 2]]); + $this->getIterator()->shouldIterateAs([['element' => 2], ['element' => 1], ['element' => 3]]); } function it_sorts_elements_by_their_priority(): void { - $this->insert(['element' => 3], -1); + $this->insert(['element' => 1], -1); $this->insert(['element' => 2], 0); - $this->insert(['element' => 1], 1); + $this->insert(['element' => 3], 1); + $this->insert(['element' => 4], 0); - $this->getIterator()->shouldIterateAs([['element' => 1], ['element' => 2], ['element' => 3]]); + $this->getIterator()->shouldIterateAs([['element' => 3], ['element' => 2], ['element' => 4], ['element' => 1]]); } } diff --git a/src/Suite/PriorityQueue.php b/src/Suite/PriorityQueue.php index 34c1fd5..99bb604 100644 --- a/src/Suite/PriorityQueue.php +++ b/src/Suite/PriorityQueue.php @@ -25,13 +25,6 @@ final class PriorityQueue implements \IteratorAggregate */ private $records = []; - /** - * @psalm-var array - * - * @var array[] - */ - private $sortedRecords = []; - /** @var bool */ private $sorted = false; @@ -44,16 +37,19 @@ public function insert(array $data, int $priority = 0): void public function getIterator(): \Traversable { if ($this->sorted === false) { - // Reversing the records to maintain FIFO order for item with the same priority - $this->sortedRecords = array_reverse($this->records); - /** @psalm-suppress InvalidPassByReference Doing PHP magic, it works this way */ - array_multisort(array_column($this->sortedRecords, 'priority'), \SORT_DESC, $this->sortedRecords); + array_multisort( + array_column($this->records, 'priority'), + \SORT_DESC, + array_keys($this->records), + \SORT_ASC, + $this->records + ); $this->sorted = true; } - foreach ($this->sortedRecords as $record) { + foreach ($this->records as $record) { yield $record['data']; } }