简体   繁体   中英

Deep flatten Scala Maps (or uJson Objs) - how to?

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.

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM