通过嵌套Map [String,Any]精确地迭代

时间:2019-07-15 15:21:45

标签: scala recursion

我有一个任意嵌套的Map[String, Any],我想遍历并更新给定路径的值。

例如,如果嵌套的Map

Map("a" -> "1", "b" -> Map("c" -> "2"))

并且路径为["b", "c"],我希望结果是

Map("a" -> "1", "b" -> Map("c" -> "null"))

到目前为止我尝试过的是

def updateMapValue(
                map: Map[String, Any],
                path: List[String]
              ): Map[String, Any] =
map map {
  case (k: String, v: String) =>
    if (k.contains(path.head)) k -> "null"
    else k -> v
  case (k: String, v: Map[String @unchecked, _]) => updateMapValue(v, path.tail)
}

但是我在这里遇到的编译错误是

Expression of type Iterable[Equals] doesn't conform to expected type Map[String, Any]

当我尝试递归调用updateMapValue时会发生。

这是怎么回事,有没有更简单的方法遍历嵌套的Map

1 个答案:

答案 0 :(得分:2)

您的代码有几个问题。首先,您使用的head会抛出异常,在这种情况下,路径列表上没有头(如果您将错误的路径传递给该方法,则会发生这种情况)。

第二,在这里case (k: String, v: Map[String, _]) => updateMapValue(v, path.tail) 您要返回的地图类型错误,您的意思可能是k -> updateMapValue(v, path.tail)

这是我的实现方式

def updateMapValue(
                    map: Map[String, _],
                    path: List[String]
                  ): Map[String, _] = {

  path match { //we iterated over path getting head
    case x :: xs => map.map {
      case `x` -> (m: Map[String, _]) => x -> updateMapValue(m, xs) //if value is map go deeped
      case `x` -> (_: String) => x -> "null" //if value is String replace with "null"
      case w => w
    }
    case Nil => map
  }

}


val m = Map("a" -> "1", "b" -> Map("c" -> "2"))
val path = List("b", "c")
updateMapValue(m, path) //Map(a -> 1, b -> Map(c -> null))

此方法不是堆栈安全的,因为它不是尾部递归的,但是如果您知道地图不会很深,则应该执行此操作。 不过,您可以使用 TailCalls 将其设为堆栈安全。