0

I have data with the following attributes: name, unit price, quantity, timestamp. e.g.

[Alice, 40.0, 20, 1000000000]
[Ben, 30.0, 35, 1000000001]
[Chris, 50.0, 25, 1000000002]
[Dolly, 20.0, 50, 1000000002]
[Erin, 20.0, 50, 1000000003]
[Fred, 30.0, 20, 1000000004]
[Gabby, 30.0, 20, 1000000005]
[Harold, 30.0, 20, 1000000005]

I am trying to store the data in a max-heap priority queue where the priority is defined by the following tie-breaking rules:

  • Highest unit price takes highest priority.
  • If there is a tie in unit price, highest quantity takes priority.
  • If there is a tie in unit price and quantity, then the timestamp takes priority.
  • If there is still a tie, then priority is assigned by name in A-Z alphabetical order.

Note that the name is not a unique attribute, but the name combined with the timestamp is unique e.g. Ben might have two entries at different times. Also, the data is not all received at the same time, so inserting into the priority queue needs to remain cheap, and priorities will continue to be updated. At the end of the day, items are finally removed from the queue in order of priority.

I am not sure how to define priority based on my tie-breaking rules. e.g. in the example above, Chris has maximum priority based on highest unit price, then Alice, then Ben before Fred (based on quantity), followed by Gabby and Harold in alphabetical order (equal timestamp but after Fred), and finally Dolly before Erin (based on timestamp priority).

I am working in PHP but I can also understand C++ code. Below is a code example for a max-heap priority queue in PHP, where the priority is just a number. Any advice on how to approach tie-breaking given my kind of data?

PHP code

<?php
$pq = new SplPriorityQueue;
 
$pq->insert('Ben', 6);
$pq->insert('Fred', 5);
$pq->insert('Harold', 3);
$pq->insert('Dolly', 2);
$pq->insert('Gabby', 4);
$pq->insert('Erin', 1);
$pq->insert('Chris', 8);
$pq->insert('Alice', 7);
 
// This line causes extract() to return both the data and priority (in an associative array),
$pq->setExtractFlags(SplPriorityQueue::EXTR_BOTH); // Otherwise it would just return the data
 
while (!$pq->isEmpty()) {
    print_r($pq->extract());
}
?>
Cogicero
  • 1,514
  • 2
  • 17
  • 36
  • How do you recieve this data? If via SQL: have looked into sorting it via a query? – Definitely not Rafal Nov 17 '20 at 15:25
  • @DefinitelynotRafal Thanks. The data is received one by one on a webpage and I can first store it in a DB. That way I can sort it using a query but that would mean sorting after each entry is received (to obtain a priority), before I can finally store the item in a priorityQueue? – Cogicero Nov 17 '20 at 15:29
  • You state that at the end of the day they are taken out of the priority queue - can you collect them and only periodically store them in the queue with the updated order/priority? – El_Vanja Nov 17 '20 at 15:35
  • 1
    From what i see you can create a object/array and make your own custom comparison (which you described as your tie breaking rules) and you can make it as complex as you want. Check this example: [click me](http://sandbox.onlinephpfunctions.com/code/0beefcba1249ff67ca57d9b6a62e2aa82d08a0d1) – Definitely not Rafal Nov 17 '20 at 15:35
  • @DefinitelynotRafal Thank you, I think that should work i.e. using custom comparisons and extending SplPriorityQueue! If you post this as an answer I will be able to accept it. – Cogicero Nov 17 '20 at 15:43
  • 1
    @Cogicero You're welcome. I will actually not repost my comment as an answer, someone else can take this and create a valid answer. Since my comment only solves part of your problem, but not your problem as a whole. My comment provides an example, but not the answer to your specific question. – Definitely not Rafal Nov 17 '20 at 15:46
  • I ran into a problem with this i.e. since the records are received sequentially, I would need to be able to "update" the priorities as they are calculated. This class seems to only allow insertion. Or maybe I couldn't figure it out. Welp. – Cogicero Nov 20 '20 at 02:32

0 Answers0