开发者

How to use scala.util.Sorting.quickSort() with arbitrary types?

开发者 https://www.devze.com 2023-01-24 06:34 出处:网络
I need to sort an array of pairs by second element. How do I pass comparator for my pairs to the quickSort function?

I need to sort an array of pairs by second element. How do I pass comparator for my pairs to the quickSort function? I'm using the following ugly approach now:

type AccResult = (AccUnit, Long) // pair
class Comparator(a:AccResult) extends Ordered[AccResult] {
        def compare(that:AccResult) = lessCompare(a, that)
        def lessCompare(a:AccResult, that:AccResult) = if (a._2 == that._2) 0 else if (a._2 < that._2) -1 else 1
}
scala.util.Sorting.quickSort(data)(d => new Comparator(d))

Why is quickSort designed 开发者_StackOverflowto have an ordered view instead of usual comparator argument?

Scala 2.7 solutions are preferred.


I tend to prefer the non-implicit arguments unless its being used in more than a few places.

type Pair = (String,Int)
val items : Array[Pair] = Array(("one",1),("three",3),("two",2))
quickSort(items)(new Ordering[Pair] {
  def compare(x: Pair, y: Pair) = {
    x._2 compare y._2
  }
})

Edit: After learning about view bounds in another question, I think that this approach might be better:

val items : Array[(String,Int)] = Array(("one",1),("three",3),("two",2))

class OrderTupleBySecond[X,Y <% Comparable[Y]] extends Ordering[(X,Y)] {
  def compare(x: (X,Y), y: (X,Y)) = {
    x._2 compareTo y._2
  }
}

util.Sorting.quickSort(items)(new OrderTupleBySecond[String,Int])

In this way, OrderTupleBySecond could be used for any Tuple2 type where the type of the 2nd member of the tuple has a view in scope which would convert it to a Comparable.


Ok, I'm not sure exactly what you are unhappy about what you are currently doing, but perhaps all you are looking for is this?

implicit def toComparator(a: AccResult) = new Comparator(a)
scala.util.Sorting.quickSort(data)

If, on the other hand, the problem is that the tuple is Ordered and you want a different ordering, well, that's why it changed on Scala 2.8.

* EDIT *

Ouch! Sorry, I only now realize you said you preferred Scala 2.7 solutions. I have editted this answer soon to put the solution for 2.7 above. What follows is a 2.8 solution.

Scala 2.8 expects an Ordering, not an Ordered, which is a context bound, not a view bound. You'd write your code in 2.8 like this:

type AccResult = (AccUnit, Long) // pair 
implicit object AccResultOrdering extends Ordering[AccResult] { 
        def compare(x: AccResult, y: AccResult) = if (x._2 == y._2) 0 else if (x._2 < y._2) -1 else 1 
}

Or maybe just:

type AccResult = (AccUnit, Long) // pair 
implicit val AccResultOrdering = Ordering by ((_: AccResult)._2)

And use it like:

scala.util.Sorting.quickSort(data)

On the other hand, the usual way to do sort in Scala 2.8 is just to call one of the sorting methods on it, such as:

data.sortBy((_: AccResult)._2)


Have your type extend Ordered, like so:

case class Thing(number : Integer, name: String) extends Ordered[Thing] {
  def compare(that: Thing) = name.compare(that.name)
}

And then pass it to sort, like so:

val array = Array(Thing(4, "Doll"), Thing(2, "Monkey"), Thing(7, "Green"))
scala.util.Sorting.quickSort(array)

Printing the array will give you:

array.foreach{ e => print(e) }
>> Thing(4,Doll) Thing(7,Green) Thing(2,Monkey)
0

精彩评论

暂无评论...
验证码 换一张
取 消