在Scala中递归求和Map的正确方法

时间:2018-01-31 13:00:20

标签: scala recursion idioms

我刚刚开始了一个项目,我们正在将一些C#工具迁移到一个新的Scala项目。这是我第一次接触语言(以及一般的函数式编程),所以为了不仅在Scala中编写Java样式代码,我想知道处理以下场景的正确方法是什么。

我们有两个地图对象,表示具有以下结构的表格数据:

map1       key|date|mapping val

map2       key|number

并不总是填充第一个对象中的映射值。目前,这些类型由Map[String, Array[String]]Map[String, Double]类型表示。

在C#工具中,我们有以下方法:

  • 循环显示第一张地图中的键集
  • 对于每个键,检查映射值是否为空白
  • 如果没有映射,则从地图2中获取数字并返回
  • 如果存在映射,则递归调用方法以获取全范围的映射值及其数字,并随时求和。例如。 key 1可能映射到键4,键4可能映射到键5等,我们想要在map2中对这些键的所有值求和。

在Scala中是否有一种聪明的方法可以避免在for循环中更新列表并递归地遍历地图?

1 个答案:

答案 0 :(得分:1)

这就是你想要的吗?

@annotation.tailrec
def recurse(key: String, count: Double, map1: Map[String, String], map2: Map[String, Double]): Double = {
  map1.get(key) match {
    case Some(mappingVal) if mappingVal == "" =>
      count + map2.getOrElse(mappingVal, 0.0)
    case Some(mappingVal) =>
      recurse(mappingVal, count + map2.getOrElse(mappingVal, 0.0), map1, map2)
    case None => count
  }
}

使用示例:

val m1: Map[String, String] = Map("1" -> "4", "4" -> "5", "5" -> "6", "8" -> "")
val m2: Map[String, Double] = Map("1" -> 1.0, "4" -> 4.0, "6" -> 10.0)

m1.map {
  case (k, _) => k -> recurse(k, 0.0, m1, m2)
}.foreach(println)

输出:

(1,14.0)
(4,10.0)
(5,10.0)
(8,0.0)

请注意,没有循环检测 - 如果map1有一个循环,这将永远不会终止。