2015-07-10 155 views
0

val mapList: List[Map[String, Int]]拼接地圖,我想要做的事,如:斯卡拉從列表

val map = mapList foldLeft (Map[String, Int]()) (_ ++ _) 

val map = mapList foldLeft (Map[String, Int]()) 
((m1: Map[String, Int], m2: Map[String, Int]) => m1 ++ m2) 

也不選項編譯(第一寫着「丟失的參數類型擴展功能(x, y) => x ++ y」第二種說法是「類型不匹配;發現(Map[String, Int], Map[String, Int]) => Map[String, Int];要求:String」)。

我想實現一個經典的解決方案來連接一個不可變的地圖列表,如List(Map("apple" -> 5, "pear" -> 7), Map("pear" -> 3, "apricot" -> 0))會產生一個Map("apple" -> 5, "pear" -> 10, "apricot" -> 0)。使用scala 2.10.5

回答

3

您需要在foldLeft之前添加一個點。你可以只用空格代替點專業的條件下,如用正好1參數(參數數量-1的方法)方法:

val map = mapList.foldLeft(Map[String, Int]()) (_ ++ _) 

你可以閱讀更多關於方法調用的最佳實踐here

您可能還對reduce方法感興趣,它們是fold方法的專用版本,其中返回類型與集合元素的類型相同。例如reduceLeft使用集合的第一個元素作爲foldLeft的種子。當然,因爲這依賴於第一個元素的存在,所以如果集合是空的,它將拋出異常。由於reduceLeft只需要1個參數,就可以更方便地使用空間要調用的方法:

mapList.reduceLeft(_ ++ _) 
mapList reduceLeft(_ ++ _) 

最後,你要注意,你這裏做的是合併的地圖。當使用++來合併地圖時,您只會覆蓋已存在於地圖中的鍵 - 您將不會添加重複鍵的值。如果你想這樣做,你可以按照提供的答案here,並將它們應用於foldLeftreduceLeft。例如:

mapList reduceLeft { (acc, next) => 
    (acc.toList ++ next.toList).groupBy(_._1).toMap.mapValues(_.map(_._2).sum) 
} 

還是略有不同:

mapList.map(_.toSeq).reduceLeft(_ ++ _).groupBy(_._1).toMap.mapValues(_.map(_._2).sum) 

而且,如果你使用Scalaz,則最簡潔:

mapList reduceLeft { _ |+| _ } 
+0

你可以使用它的元數-1的方法或方法0(儘管後者通常是灰心的)。您不能將它用於具有多個參數或多個參數列表的方法。 –

+1

更加簡潔地使用scalaz:'mapList.suml'。 – lmm

+0

@Imm非常好! –