【问题标题】:How to sum a List[(Char,Int)] into a Map[Char,Int] in Scala?如何在 Scala 中将 List[(Char,Int)] 加到 Map[Char,Int] 中?
【发布时间】:2016-09-05 16:58:32
【问题描述】:

我有配对列表:

List(('a',3),('b',3),('a',1))

我想通过按 _1 分组并对 _2 求和来对其进行转换。结果应该是这样的

Map('a'->4, 'b' -> 3)

我对 Scala 很陌生,所以请善待 :)

【问题讨论】:

    标签: scala scala-collections


    【解决方案1】:

    更直接的版本。我们折叠列表,使用 Map 作为累加器。 withDefaultValue 意味着我们不必测试我们是否已经在地图中有条目。

    val xs =  List(('a',3),('b',3),('a',1))
    
    xs.foldLeft(Map[Char, Int]() withDefaultValue 0)
               {case (m, (c, i)) => m updated (c,m(c)+i)}
    
    //> res0: scala.collection.immutable.Map[Char,Int] = Map(a -> 4, b -> 3)
    

    【讨论】:

    • 好的,一个问题:当我将代码直接复制到工作表时它可以工作,但是当我这样做时:List(('a', 3), ('b', 3), ('a', 1)) foldLeft(Map[Char, Int]() withDefaultValue 0) {case (m, (c, i)) => m updated (c,m(c)+i)} 它给了我一个错误,说updated: 无法解析符号。当我将. 放在 List(......).foldLeft(.......) 之间时没问题,但没有它,编译器就会出现问题。
    • 优先级问题,我想。 (list foldleft Map...) 周围的括号也可以修复它。
    【解决方案2】:
    list.groupBy(_._1).mapValues(_.map(_._2).sum)
    

    可以写成

    list.groupBy(_._1).mapValues { tuples => 
      val ints = tuples.map { case (c, i) => i }
      ints.sum
    }
    

    【讨论】:

    • 这可能是最简单的方法,但它会创建一堆无关的Lists,并且需要通过与每个键关联的值进行额外的迭代以获得总和.
    • @JasonLenderman 你有什么建议? view?我也在学习。
    • .view 附加到list 会产生相同的输出并在我认为是轻量级的过程中产生SeqView*s。
    • 明确一点,mapValues 实际上总是创建一个视图。这是使用 mapValues 的危险之一,从名称上看并不明显。
    • 问题不是view。问题发生在groupBy,它创建了一堆(不必要的)Lists。列表的总和可以以流式方式计算,因此没有理由首先创建这些列表。这基本上与 groupBy 相同的问题,然后是 reduce 与 Spark 中的 reduceByKey。为了提高效率,您总是希望使用后者。
    猜你喜欢
    • 1970-01-01
    • 2016-03-07
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-01
    • 1970-01-01
    • 2016-07-31
    相关资源
    最近更新 更多