2016-08-04 25 views
-1

Ich versuche den folgenden scala code zu konvertieren?scala map string -> string in string -> map konvertieren

val orig = Map("command.stamp" -> 5, "command.another" -> "0", "level1.level2.level3" -> 10) which would translate to 

zu einer Karte. neue Karte muss mehrere Werttypen und mehr als zwei Ebenen unterstützen

val newMap = Map("command" -> Map("stamp" -> 5, "another" -> "0"), "level1" -> Map("level2" -> Map("level3" -> 10))) 

Zusätzlich muss ich es in JSON konvertieren. Json.toJson (newMap) verwendet, aber es hat wahrscheinlich mit mehreren Typen.

Antwort

0

Unter der Annahme, dass Sie immer das Schlüsselmuster haben „one.two“ dies funktionieren wird:

val orig = Map("command.stamp" -> 5, "command.another" -> 0) 

newMap = orig.foldLeft(immutable.Map[String, Map[String, Int]]())((prev, elem) => { 
    val ar = elem._1.split('.') 
    prev.get(ar(0)) match { 
    case None => (prev + (ar(0) -> immutable.Map((ar(1), elem._2)))) 
    case Some(entry) => 
     prev + (ar(0) -> (immutable.Map((ar(1), elem._2)) ++ entry)) 
    } 
}) 

grundsätzlich Iam Faltung und die Ausgabe der Karte ausbreitet. Der erste Fall prüft nur, ob für diesen Schlüssel bereits ein Eintrag vorhanden ist. Andernfalls wird die Wertemappe extrahiert und explizit angehängt. Es weiß nicht, ob das die beste Lösung ist. Ich dachte über Version mit Zip und andere iterative Ansätze, aber es gab keine.

+0

Das funktioniert aber mein Anwendungsfall ist ein wenig anders dann dachte ich – richs

+0

@Mikel tat die gleichen, aber in einer besseren Art und Weise. Sagen Sie mir, wie sich Ihr Anwendungsfall unterscheidet oder bearbeiten Sie die Frage entsprechend. Vielleicht wird das helfen. – sascha10000

+0

Ich habe die Frage bearbeitet – richs

1

ich tun würde, diese

map.foldLeft(Map[String,Map[String,Int]]()) { 
    case (map, (k,v)) => 
     val keys = k.split('.') 
     map + ((keys(0), map.getOrElse(keys(0), Map[String,Int]()) + (keys(1) -> v))) 
    } 
0

übernehmen wir eine testMap andere Präfix Gruppe für Demozwecke ergänzt: ""

val testmap:Map[String,Int] = Map("command.stamp" -> 5, "command.another" -> 0, 
            "command2.stamp2" -> 4, "command2.another2" -> 1) 

Wir können zuerst von tokenize und Gruppe durch das Präfix und in zweiter Linie jedes Teilabbildungs ​​analysiert das Präfix abzuzustreifen:

for { 
    (k,v) <- testmap.groupBy{ _._1.split("\\.")(0) } //first tokenize by "." and group by prefix 
    } yield (k -> v.map{case(subKey,subValue) => subKey.replace(k,"").replace("\\.","") -> subValue }) //stripping prefix from submaps 
3
scala> map.groupBy(_._1.split('.')(0)) 
      .mapValues(_ map { case(k, v) => (k.split('.')(1), v) }) 
res1: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,Int]] = 
      Map(command -> Map(stamp -> 5, another -> 0))