1

I've defined a priority queue like so

import scala.collection.mutable.PriorityQueue
...
val queue = new PriorityQueue[(Int,Int)]()

I want to use this ordering:

If we are comparing two items A and B in the queue, A is bigger than B if the first element of its (Int,Int) tuple is larger than B's. If they're the same, then A is bigger than B if the second element of its (Int,Int) tuple is smaller than B's.

How do I define this kind of ordering?

  • Added code to the OP – user5019849 Jun 17 '15 at 13:41
  • Simplified my post to get at the heart of the problem – user5019849 Jun 17 '15 at 13:48
  • Also, to answer the questions from before the edit: PriorityQueue is not deprecated, it's only `deprecatedInheritance`, so you shouldn't `extends` it, but can use it normally. You can add items with `queue += item` or `queue.enqueue(item)`, find the largest with `queue.head`, and get+remove the largest item with `queue.dequeue()` – Kolmar Jun 17 '15 at 14:04
  • Is there any significant difference between += and enqueue or does + call enqueue anyway? – user5019849 Jun 17 '15 at 14:06
  • `enqueue` takes several items and adds all of them: `q.enqueue(a, b, c, d)` adds a, b, c and d. `++=` takes an *iterable* of items and adds all of them. `+=` takes only a single item. And `++` takes a sequence as well, but *clones* the queue before adding them. – Kolmar Jun 17 '15 at 14:15

1 Answers1

1

If your elements are Ints, the easiest way to define such an Ordering is by taking a negative of the elements which should be ordered in reverse.

You can create the Ordering, using methods provided by the object Ordering, and pass it to the PriotityQueue either explicitly:

// I'm using the data format, you have provided originally, before the edit
val queue = PriorityQueue(
  (1, (2,3), (4,5)), 
  (2, (3,4), (5,6)), 
  (2, (4,5), (6,7))
)(Ordering.by {
  case (fst, (snd, _), (_, _)) => (fst, -snd)
})

Or implicitly:

implicit val MyOrdering: Ordering[(Int, (Int, Int), (Int, Int))] = 
  Ordering.by {
    case (fst, (snd, _), (_, _)) => (fst, -snd)
  }
val queue = PriorityQueue(
  (1, (2,3), (4,5)), 
  (2, (3,4), (5,6)), 
  (2, (4,5), (6,7)))
Kolmar
  • 13,241
  • 1
  • 19
  • 24
  • What does the implicit thing mean? That all priority queues are implicitly ordered according to MyOrdering? How does Scala know when to apply the implicit ordering and to what? – user5019849 Jun 17 '15 at 14:02
  • If you define or import the implicit in a function, than it's everything until the end of the function. If you define it in a class, than it's everywhere whitin this class. But you can still pass implicit parameters explicitly. Also read here about kinds of implicits, and where they can come from: http://stackoverflow.com/questions/5598085/where-does-scala-look-for-implicits – Kolmar Jun 17 '15 at 14:07
  • Actually part of this answer may not be working for me. What is wrong with `val queue = PriorityQueue[(Int,Int)]( Ordering.by {case (a,b) => (a, -b)} )`? It gives me the error `error: missing parameter type for expanded function` – user5019849 Jun 17 '15 at 14:12
  • 1
    @user5019849 First argument is the items, Ordering is the second argument. So it should be `PriorityQueue[(Int,Int)]()( Ordering.by {case (a,b) => (a, -b)} )` with one more pair of brackets. – Kolmar Jun 17 '15 at 14:16
  • So in the examples you posted you didn't need to explicitly list [(Int,Int)] because it infers this from the arguments you passed in? – user5019849 Jun 17 '15 at 14:19
  • @user5019849 Yes, that's right. It also infered Ordering's type in the first example, but I had to specify it in the second example. – Kolmar Jun 17 '15 at 14:21