Reputation: 1429
How can I flatten deep nested Maps in Scala returning a new map with the relevant nested key in dot notation?
Background: I am trying to do so for uJson.Obj
s, but since they are just mutable.LinkedHashMap[String, Value]
under-the-hoods, answers for standard library maps should help as well.
For example:
val original = Obj("Simple" -> "a",
"nested" ->
Obj("c1" ->
Obj("c2" -> "a")))
flattenObj(original) shouldEqual Obj("simple" -> "a", "nested.c1.c2" -> "a")
I have tried the following (based on this answer), but it works only for the first level, and still don't deal with naming new keys in dot notation:
def flattenObj(o: Obj, delimiter: String = "."): Obj = {
o.obj.flatMap {
case (key, map: Obj) => map.obj
case (key, value) => Map(key -> value)
}
}
It results in:
Actual: {"Simple":"a","c1":{"c2":"a"}}
But, I expect:
Expected: {"simple":"a","nested.c1.c2":"a"}
Thank you all.
Upvotes: 0
Views: 294
Reputation: 1429
Final implementation based on the @Raf's guidance in the comments:
def flattenObj(o: Obj, keyAcc: String = "", delimiter: String = "."): Obj = {
o.obj.flatMap(kv => {
val key: String = if (keyAcc.isEmpty) kv._1 else keyAcc + delimiter + kv._1
kv._2 match {
case map: Obj => flattenObj(map.obj, key, delimiter).obj
case value => Map(key -> value)
}
})
}
Thank you Raf.
Upvotes: 0