YFl
YFl

Reputation: 1429

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.Objs, 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

Answers (1)

YFl
YFl

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

Related Questions