递归遍历 Map 中的值

Recursively walk values in Map

我正在尝试递归地遍历 Map[String,List[String]] 以提取并展平与 Map

关联的所有值
val x = Map("a" -> List("b","c","d"), "b" -> List("f","g","h"), "f" -> List("i","j","k"), "g" -> List("p","q","r"))
  1. 对于每个键,提取值,即列表
  2. 对于列表值中的每一项:
    • 检查键是否存在然后提取值

递归地继续这样做,直到键没有值并展平键列表的值

结果应该是

Map("a" -> List("b","c","d","f","g","h","i","j","k","p","q","r"), 
    "b" ->  List("f","g","h","i","j","k","p","q","r"), 
    "f" -> List("i","j","k"), 
    "g" -> List("p","q","r"))

试试这个代码:

def f(map: Map[String, List[String]]): Map[String, List[String]] = {
  def f(x: Map[String, List[String]], acc: Map[String, List[String]]): Map[String, List[String]] = {
    if (x.isEmpty) acc
    else {
      val keys = x.keySet
      val (complex, simple) = x partition {_._2 exists {s => keys contains s}}

      val newX =
        (for ((ck, cl) <- complex)
        yield (ck -> (simple.filter(x => cl.contains (x._1)).map(_._2).flatten ++ cl).toList)).toMap

      f(newX, acc ++ simple)
    }
  }

  f(map, Map.empty)
}

val x = Map("a" -> List("b","c","d"), "b" -> List("f", "g", "h"), "f" -> List("i","j","k"), "g" -> List("p","q","r"))

println(f(x)) //Map(f -> List(i, j, k), g -> List(p, q, r), b -> List(i, j, k, p, q, r, f, g, h), a -> List(i, j, k, p, q, r, f, g, h, b, c, d))

但是假设地图中没有递归,例如("a" -> List("b")), ("b" -> List("a")。如果发生这种情况,该函数将以无限循环结束。您将不得不添加额外的代码来处理这种情况。

你可以尝试迭代直到没有变化:

def getValues(dict: Map[String, List[String]]) = Iterator.iterate(dict) { _.mapValues { 
        _.flatMap(v => v :: dict.get(v).toList.flatten).toSet.toList
    } filterNot { _._2.isEmpty }
}.sliding(2) find { x => x.head == x.last }

这绝对不是最有效的解决方案,但它非常简洁!