2012-05-17 90 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