es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo realizar un aplanamiento profundo de los Mapas de Scala (o los Objs de uJson)?

¿Cómo puedo aplanar Mapas anidados en Scala devolviendo un nuevo mapa con la clave anidada relevante en notación de punto?

Antecedentes: Estoy tratando de hacerlo para objetos uJson.Obj, pero dado que son simplemente mutable.LinkedHashMap[String, Value] internamente, las respuestas para los mapas de la biblioteca estándar también deberían ayudar.

Por ejemplo:

   val original = Obj("Simple" -> "a",
        "nested" ->
          Obj("c1" ->
            Obj("c2" -> "a")))

flattenObj(original) debería ser igual a Obj("simple" -> "a", "nested.c1.c2" -> "a")

He intentado lo siguiente (basado en esta respuesta), pero solo funciona para el primer nivel y aún no trata de nombrar las nuevas claves en notación de punto:

    def flattenObj(o: Obj, delimiter: String = "."): Obj = {
      o.obj.flatMap {
        case (key, map: Obj) => map.obj
        case (key, value) => Map(key -> value)
      }
    }

Esto resulta en:

Actual: {"Simple":"a","c1":{"c2":"a"}}

Pero espero:

Esperado: {"simple":"a","nested.c1.c2":"a"}

Gracias a todos.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para aplanar mapas anidados en Scala y devolver un nuevo mapa con la clave anidada relevante en notación de puntos, puedes usar una función recursiva. Aquí tienes un ejemplo de implementación:

    import ujson._
    
    def flattenObj(obj: Obj, prefix: String = ""): Map[String, Value] = {
      obj.obj.flatMap {
        case (key, value: Obj) =>
          flattenObj(value, prefix + key + ".")
        case (key, value) =>
          Map(prefix + key -> value)
      }
    }
    
    val original = Obj("Simple" -> "a",
      "nested" ->
        Obj("c1" ->
          Obj("c2" -> "a")))
    
    val flattened = flattenObj(original)
    
    println(flattened)
    // salida: Map(simple -> Str(a), nested.c1.c2 -> Str(a))
    

    La función flattenObj recibe un objeto Obj y una cadena prefix opcional (que inicialmente es una cadena vacía). Aplana recursivamente los mapas anidados, concatenando las claves usando la notación de puntos y agregando el prefix a las claves anidadas.

    La función utiliza el método flatMap en la propiedad obj del objeto Obj. Si una clave se asigna a otro Obj, la función se llama a sí misma de forma recursiva con el valor y un nuevo prefijo. De lo contrario, devuelve un mapa con la clave concatenada con el prefijo.

    Ten en cuenta que esta implementación asume que las claves en el objeto Obj original no están en notación de puntos. Si lo están, es posible que debas modificar la función para manejarlas correctamente.

Comments are closed.