0
votes

SCALA: Transformer une liste en une carte imbriquée

J'ai une classe de configuration définie comme xxx pré>

et une liste: p> xxx pré>

donné une liste de configuration, je veux une carte de la propriété -> Carte des entrées qui répondent à la propriété p>

à titre d'exemple, si j'ai p> xxx pré>

i obtenez le résultat p>

res0: Map[String,Map[String,String]] =
Map(
  "general" ->
    Map(
      "first" -> "general first value",
      "second" -> "general second value"
    ),
  "custom" ->
    Map(
      "first" -> "custom first value",
      "second" -> "custom second value"
    )
)


1 commentaires

Il y aura toujours deux et seulement deux parties de la clé? Ainsi, ce sera toujours un mappe [String, mappe [String, String]]] ? Ou peut-il être infiniment imbriqué?


3 Réponses :


2
votes

Vous pouvez faire quelque chose comme ceci:

def getConfig(data: List[ConfigEntry]): Config = {
  @annotation.tailrec
  def loop(remaining: List[ConfigEntry], acc: Config): Config =
    remaining match {
      case ConfigEntry(key, value) :: xs =>
        val newAcc = key.split('.').toList match {
          case k1 :: k2 :: Nil =>
            acc.updatedWith(k1) {
              case Some(map) =>
                val newMap = map.updatedWith(k2) {
                  case Some(v) =>
                    println(s"Overwriting previous value ${v} for the key: ${key}")
                    // Just overwrite the previous value.
                    Some(value)

                  case None =>
                    Some(value)
                }
                Some(newMap)

              case None =>
                Some(Map(k2 -> value))
            }

          case _ =>
            println(s"Bad key: ${key}")
            // Just skip this key.
            acc
        }
        loop(remaining = xs, newAcc)

      case Nil =>
        acc
    }

  loop(remaining = data, acc = Map.empty)
}


0 commentaires

2
votes

Votre carte ne produira qu'un résultat de 1 à 1. Pour faire ce que vous voulez, vous aurez besoin d'un accumulateur (carte existante) pour le faire.

Utilisation de votre code existant, si vous êtes particulièrement attaché à la manière dont vous analyse vos clés primaire et secondaire via Getkey, vous pouvez appliquer pli à votre liste à la place, avec une carte vide comme valeur initiale. xxx


0 commentaires

0
votes

Simplement:

list.map { ce =>
  val Array(l, r) = ce.key.split("\\.")
  l -> (r -> ce.value)
}                                                 // List[(String, (String, String))]
.groupBy { case (k, _) => k }                     // Map[String, List[(String, (String, String))]]
.view.mapValues(_.map { case (_, v) => v }.toMap) // MapView[String, List[(String, String)]]
.toMap                                            // Map[String, Map[String, String]]


0 commentaires