Just use recursion as in any other programming language (it's not something Scala-specific).
val m: Map[String, Any] = Map("a" -> Map("b" -> Map("c" -> 1, "d" -> 4)))
def traverse(el: Any, acc: List[String] = List.empty[String]): Map[String, Int] = el match {
case leaf: Int => Map(acc.reverse.mkString(".") -> leaf)
case m: Map[String, Any] => m flatMap {
case (k, v) => traverse(v, k :: acc)
}
}
traverse(m)
res2_2: Map[String, Int] = Map("a.b.c" -> 1, "a.b.d" -> 4)
Btw,
1) the presented solution is not tail-recursive (so might throw stack-overflow on very deep trees) - you could write tail-recursive version as an exercise. Hint - you would need an accumulator for resulting collection (or use mutable buffer, idn, maybe you're not really into functional programming and was forced to use Scala by employer :) ).
2) List
is inappropriate structure for accumulator (coz of performance), I was just lazy to use less common one, as you were lazy to try to at least somehow implement this trivial algorithm. I bet there should be a duplicate question on SO, but again, lazy to look for it :).
3) @unchecked
annotation would be appropriate at some place in my code (guess where?). And also default case for pattern matching (you can build a test case that breaks my function to figure out why).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…