2010-11-06 17 views
0

我需要按第二個元素對數組進行排序。我如何將比較器傳遞給quickSort函數? 我現在使用下面的醜陋做法:如何使用任意類型的scala.util.Sorting.quickSort()?

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)) 

爲什麼QUICKSORT設計有一個有序的視圖,而不是通常的比較論證?

斯卡拉2.7解決方案是首選。

回答

2

好吧,我不確定你對你現在在做什麼感到不滿,但也許你是全部尋找是這樣嗎?

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

如果,另一方面,問題是,元組Ordered,你想一個不同排序,那麼,這就是爲什麼它改變了斯卡拉2.8。

*編輯*

哎喲!對不起,我現在才意識到你說你喜歡Scala 2.7解決方案。我很快編輯了這個答案,將2.7的解決方案放在上面。接下來是2.8解決方案。

Scala 2.8預計Ordering,而不是Ordered,這是一個上下文綁定,而不是視圖綁定。你會寫你的代碼在2.8這樣的:

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 
} 

或者,也許只是:

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

而且使用它像:

scala.util.Sorting.quickSort(data) 

在另一方面,通常的辦法在Scala 2.8中進行排序只是調用其中的一種排序方法,如:

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

隱式對象被破壞b/c參數是x和y,代碼處理a和那個。 – 2010-11-06 13:13:03

+0

@Hoodiecrow Argh ... – 2010-11-06 13:16:07

+0

因此,我仍然需要實現一個自定義類並使用2.7中的視圖。 2.8好多了。我不能等待它被debian測試所採用。 – Basilevs 2010-11-06 19:39:26

2

有你喜歡的類型擴展Ordered,就像這樣:

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

然後通過它進行排序,像這樣:

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

打印陣列會給你:

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

該類型是固定的 - 它是一對(smth,Long)。第二個領域是要比較。我如何讓這個對繼承Ordered? – Basilevs 2010-11-06 11:53:52

+0

我想你應該看看科林的回答,我認爲這是該主題中最好的一個。 – 2010-11-06 16:55:18

2

我傾向於更喜歡非隱式參數,除非它在多個地方使用。

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 
    } 
}) 

編輯:學習有關的另一個問題視圖界限之後,我認爲,這種做法可能會更好:

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]) 

這樣,OrderTupleBySecond可用於任何Tuple2類型,其中的類型元組的第二個成員有一個範圍內的視圖,將其轉換爲Comparable。