2010-04-21 48 views
6

我從scala 2.7切換到命令scala 2.8並使用排序。它看起來非常直截了當,但我想知道我能否讓它稍微冗長些。例如:Scala 2.8 TreeMap和自定義排序

scala> case class A(i: Int) 
defined class A 
scala> object A extends Ordering[A] { def compare(o1: A, o2: A) = o1.i - o2.i} 
defined module A 

如果我再嘗試創建一個TreeMap我得到一個錯誤

scala> new collection.immutable.TreeMap[A, String]() 
<console>:10: error: could not find implicit value for parameter ordering: Ordering[A] 
     new collection.immutable.TreeMap[A, String]() 
    ^

但是,如果我明確指定對象A作爲訂購它工作正常。

scala> new collection.immutable.TreeMap[A, String]()(A) 
res34: scala.collection.immutable.TreeMap[A,String] = Map() 

我是否總是必須明確指定順序或是否有更短的格式?

感謝

+1

警告:通過減去它們來比較ints是行不通的。也適用於這裏給出的大多數答案。 http://stackoverflow.com/questions/2728793/java-integer-what-is-faster-comparison-or-subtraction – 2012-03-19 20:17:30

+0

... * iff *整數是*大*並且具有相反的符號。自從符號切換以後,該數字可能會溢出,產生相反的結果。但是,如果您正在處理*接近'Int.MAX_VALUE'的數字,那麼您已經在玩火了,對不對?我認爲減法「成語」在scala中特別簡潔/有用,因爲scala沒有(三元)條件表達式(?:) – kornfridge 2012-12-13 15:54:40

回答

10

請注意,在診斷單詞 「隱」。該參數聲明爲implicit,這意味着編譯器將嘗試在調用構造函數的位置處找到合適的值。如果你讓你訂購一個隱含的價值,這將有資格獲得這種治療編譯器:

scala> implicit object A extends Ordering[A] { def compare(o1: A, o2: A) = o1.i - o2.i} 
defined module A 

scala> val tm1 = new collection.immutable.TreeMap[A, String]() 
tm1: scala.collection.immutable.TreeMap[A,String] = Map() 

編輯:

這個例子作品在REPL因爲REPL隱形類定義包圍你的代碼。這裏有一個工程自立:

case class A(val i:Int) extends Ordered[A] { def compare(o:A) = i - o.i } 

object A { implicit object AOrdering extends Ordering[A] { def compare(o1: A, o2: A) = o1.i - o2.i } } 

class B { 
    import A.AOrdering 

    val tm1 = new collection.immutable.TreeMap[A, String]() 
} 
+0

如果我在我的代碼中嘗試,我會被告知「error:'implicit'修飾符不能使用爲頂級對象「。那麼有沒有這樣做的頂級對象的方式? – Dave 2010-04-21 15:25:12

+0

@Dave沒有,但是你可以在包含'A'的包的包對象中放置這樣一個隱式。 – 2010-04-21 22:51:57

+0

@Daniel:你試過了嗎?我做了,但不知何故被編譯器拒絕了。我不知道我是否做錯了,或者真的不允許。 – 2010-04-21 23:09:09

5

不是擴展Ordering[A],儘量延長Ordered[A]。像這樣:

scala> case class A(val i:Int) extends Ordered[A] {def compare(o:A) = i-o.i} 
defined class A 

scala> A(1)<A(2) 
res0: Boolean = true 

scala> A(1)<A(0) 
res1: Boolean = false 

scala> new collection.immutable.TreeMap[A, String]() 
res3: scala.collection.immutable.TreeMap[A,String] = Map() 
+1

工作方式是低優先級隱式將有序[A]轉換爲TreeMap的排序[A]。不幸的是,我們序列化TreeMaps的存儲和排序類是有點不穩定(一些$ anon $類)。 – Dave 2010-04-22 09:09:02

13

你要知道,有創建Ordering的略少冗長方式:

implicit val OrderingA = Ordering.by((_: A).i) 

排序是你可以爲同一類提供了許多人的主要優點。如果你的A課程確實是Ordered,那麼你應該擴展它。如果不是,而不是使用implicits,則可以明確地傳遞一個Ordering:

new collection.immutable.TreeMap[A, String]()(Ordering.by(_.i)) 
+0

看起來簡潔,易於理解和靈活。 – javadba 2014-05-15 02:26:38

+0

再次來到這裏,想upvote/comment但是..我已經在那裏做了! – javadba 2014-10-17 21:26:03