【问题标题】:Scala foldLeft adding one more element?Scala foldLeft 添加了一个元素?
【发布时间】:2012-05-25 02:18:07
【问题描述】:

我正在尝试在 scala 中创建一个按座位飞行的稀疏向量库,但我遇到了 foldLeft 的问题,它似乎是在长度为 1 的序列上创建或添加额外的元素。

这是我的稀疏加法函数:

  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,因此我所要做的就是除以参数序列的长度,以确保生成的映射总和为其值的 1)

作为一个测试用例,如果我添加两个值总和为 1 的地图,结果很好:

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)

【问题讨论】:

    标签: scala


    【解决方案1】:

    你的addTwoMaps有错字,应该是:

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

    您需要在m1 上调用getOrElse,而不是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 的一部分。

    【讨论】:

    • 天啊!是的,这解决了一切。谢谢!
    猜你喜欢
    • 2022-12-10
    • 2022-07-25
    • 2017-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多