2012-05-17 91 views
1

我正在嘗試在scala中創建一個坐在褲子中的稀疏矢量庫,並且我正在用foldLeft創建一個問題,它似乎是在長度爲1的序列上創建或添加了一個額外的元素。斯卡拉foldLeft添加一個元素?

這是我稀疏的新增功能:

def addTwoMaps(m1: Map[Int,Double], m2: Map[Int,Double]) = 
    m1 ++ m2.map{ case (k,v) => k -> (v + m2.getOrElse(k, 0.)) } 

這是我的「添加了序列圖/稀疏矢量和規範」的功能:

def addNMaps(ms : Map[Int, Double]*) = { 
val denom = if (ms.length > 0) ms.length.toDouble else 1 
ms.foldLeft(Map.empty[Int, Double])((a,b) => addTwoMaps(a,b)).mapValues(_/denom) 
} 

(針對我的具體情況,該值每個輸入映射總和爲1,所以我必須除以參數序列的長度以確保結果映射與其值相加)

作爲測試c日月光,如果我添加了具有價值的那筆一兩張地圖,它工作了罰款:

scala> Common.addNMaps(Map(1->1), Map(1->1)) 
res34: scala.collection.immutable.Map[Int,Double] = Map(1 -> 1.0) 

但如果我只有一個參數:

scala> Common.addNMaps(Map(1->1)) 
res33: scala.collection.immutable.Map[Int,Double] = Map(1 -> 2.0) 

值總和兩個所有的突然!我的猜測是單個Map(1->1)正在foldLeft中以某種方式添加兩次,但這只是一個猜測。

我在做什麼錯?我怎樣才能得到Common.addNMaps(Map(1->1))返回Map(1->1.0)

回答

1

有一個在你的addTwoMaps一個錯字,應該是:

def addTwoMaps(m1: Map[Int,Double], m2: Map[Int,Double]) = 
    m1 ++ m2.map{ case (k,v) => k -> (v + m1.getOrElse(k, 0.)) } 

你需要調用getOrElsem1,不m2


注意,在這種情況下,你可以使用IntMap,它有一個方便的unionWith法(Haskell's Data.Map.unionWith大概啓發):

import scala.collection.immutable.IntMap 

def addNMaps(ms : IntMap[Double]*) = { 
    val denom = if (ms.length > 0) ms.length else 1 
    ms.foldLeft(IntMap.empty[Double]) { 
    (a, b) => a.unionWith(b, (_, x, y) => x + y) 
    }.mapValues(_/denom) 
} 

我不知道爲什麼unionWith不是一部分標準的Scala Map API。

+0

D'oh!是的,這固定了一切。謝謝! – JasonMond