【问题标题】:Getting a HashMap from Scala's HashMap.mapValues?从 Scala 的 HashMap.mapValues 获取 HashMap?
【发布时间】:2014-01-04 00:35:16
【问题描述】:

下面的示例是我从较大的应用程序中提取的一个独立示例。

在下面调用 mapValues 后,有没有更好的方法来获取 HashMap?我是 Scala 的新手,所以很可能我做错了,在这种情况下,请随意提出一种完全不同的方法。 (一个显而易见的解决方案是将mapValues 中的逻辑移动到accum 内部,但这在较大的应用程序中会很棘手。)

#!/bin/sh
exec scala "$0" "$@"
!#

import scala.collection.immutable.HashMap

case class Quantity(val name: String, val amount: Double)

class PercentsUsage {
  type PercentsOfTotal = HashMap[String, Double]

  var quantities = List[Quantity]()

  def total: Double = (quantities map { t => t.amount }).sum

  def addQuantity(qty: Quantity) = {
    quantities = qty :: quantities
  }

  def percentages: PercentsOfTotal = {
    def accum(m: PercentsOfTotal, qty: Quantity) = {
      m + (qty.name -> (qty.amount + (m getOrElse (qty.name, 0.0))))
    }
    val emptyMap = new PercentsOfTotal()

    // The `emptyMap ++` at the beginning feels clumsy, but it does the
    // job of giving me a PercentsOfTotal as the result of the method.
    emptyMap ++ (quantities.foldLeft(emptyMap)(accum(_, _)) mapValues (dollars => dollars / total))
  }
}

val pu = new PercentsUsage()

pu.addQuantity(new Quantity("A", 100))
pu.addQuantity(new Quantity("B", 400))

val pot = pu.percentages
println(pot("A")) // prints 0.2
println(pot("B")) // prints 0.8

【问题讨论】:

  • 出于好奇——你为什么不把PercentsOfTotal定义为Map,而不是HashMap
  • error: trait Map is abstract; cannot be instantiated
  • 使用Map()。我猜所有的 scala 集合类型都不能由构造函数创建。看scala.collection.Map#apply方法
  • 如果我将PercentsOfTotal 定义为Map[String, Double],那么我会在new PercentsOfTotal() 收到“无法实例化”消息。我可以将其更改为emptyMap = Map[String, Double],但是拥有类型别名有什么意义呢?
  • 请注意,total 将针对每个数量进行重新计算,这使您完全处于二次时间区域,这不是您想要的位置。

标签: scala scala-collections


【解决方案1】:

与其使用可变的HashMap 来构建您的Map,不如使用Scala 集合内置的groupBy 函数。这会创建一个从分组属性到该组中值列表的映射,然后可以对其进行聚合,例如取总和:

def percentages: Map[String, Double] = {
   val t = total
   quantities.groupBy(_.name).mapValues(_.map(_.amount).sum / t)
}

此管道转换您的 List[Quantity] => Map[String, List[Quantity]] => Map[String, Double] 为您提供所需的结果。

【讨论】:

    猜你喜欢
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-10
    • 1970-01-01
    相关资源
    最近更新 更多