2011-06-23 45 views

回答

45

信不信由你,這個工程:

val b = List(1, 2) 
b map({case 1 => "one" 
     case 2 => "two"}) 

您可以在簡單的情況下跳過p => p match。所以這應該工作:

val c = a map {case ((x,y) -> u) => 
    (y,x) -> u 
} 
+0

優秀。謝謝。 – Owen

+18

你可以跳過一對parens /括號:'b map {case 1 =>「one」; case 2 =>「two」}' –

+0

有了這些結構,我會建議總是明確地鍵入你正在映射的集合。否則,意外擴大靜態類型(通過類型推斷或重構)可能會導致直到運行時才能檢測到的類型錯誤:https://issues.scala-lang.org/browse/SI-4670 –

10

在你引用的例子,最乾淨的解決方案是:

val xs = List((1,2)->3,(4,5)->6,(7,8)->9) 
xs map { case (a,b) => (a.swap, b) } 
4
val b = a map { case ((x,y), u) => ((y,x), u) } 
17

在你的榜樣,有可能會持續三個略有不同的語義。

  1. 在集合上映射,轉換每個匹配模式的元素。如果任何元素不匹配,則拋出異常。這些語義與

    val b = a map { case ((x, y), u) => ((y, x), u) } 
    
  2. 地圖上收集來實現,將每個匹配模式元素。默默地丟棄不匹配的元素:

    val b = a collect { case ((x, y), u) => ((y, x), u) } 
    
  3. 在集合上映射,安全解構,然後轉換每個元素。這些是我期望的表達式的語義,如

    val b = a map (((x, y), u) => ((y, x), u))) 
    

    不幸的是,在Scala中沒有簡潔的語法來實現這些語義。 相反,你必須自己解構:

    val b = a map { p => ((p._1._2, p._1._1), p._2) } 
    

    人們可能會傾向於使用值定義爲解構:

    val b = a map { p => val ((x,y), u) = p; ((y, x), u) } 
    

    但是,此版本is no more safe than the one that uses explicit pattern matching。出於這個原因,如果你想安全解構語義,最簡潔的解決方案是明確地鍵入您的收藏以防止意外擴大和使用明確的模式匹配:

    val a: List[((Int, Int), Int)] = // ... 
    // ... 
    val b = a map { case ((x, y), u) => ((y, x), u) } 
    

    如果a的定義與它的使用遠看似(例如,在一個單獨的編譯單元),你可以在地圖調用歸咎於其類型的風險降到最低:

    val b = (a: List[((Int, Int), Int)]) map { case ((x, y), u) => ((y, x), u) } 
    
+1

不錯的工作指出了細微差異。 – AmigoNico

相關問題