2017-09-18 16 views
-1

分开键和值的字符串我有一个Map[String, Any]。该值可以是另一个Map等。如何使一个嵌套的地图为点Scala的

val m: Map[String, Any] = Map("a" -> Map("b" -> Map("c" -> 1, "d" -> 4))) 

什么是该嵌套Map到另一个Map与转换价值像

Map("a.b.c" -> 1, "a.b.d" -> 4) 
+0

发生了什么事,当你实现了吗? – Dima

+0

我对scala很新。所以,我无法实现它。 – Deepakkumar

+0

那么,你试过吗? – Dima

回答

3

只需使用递归就像在任何其他的编程语言(它不是具体的斯卡拉 - )的最佳方式。

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) 

顺便说一句,

1)所提出的解决方案是不是尾递归(所以可能会引发在非常深的树木堆栈溢出) - 你可以写尾递归版本作为练习。提示 - 你需要一个累加器来进行结果集合(或者使用可变缓冲区,idn,也许你并不是真的进入函数式编程,并被雇主用于Scala)。

2)List是累加器的不适当的结构(因为performance),我只是懒惰地使用较不常见的结构,因为你懒得试图至少以某种方式实现这个微不足道的算法。我敢打赌,这应该是一个重复的问题,但再次,懒得去找它:)。

3)@unchecked注释会在我的代码一些地方(猜在哪里?)是合适的。还有模式匹配的默认情况(你可以构建一个测试用例来打破我的功能,找出原因)。