2016-08-04 3 views
-1

Я пытаюсь преобразовать следующий код scala?convert scala map string -> string to string -> map

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

на карте. новая карта должна поддерживать несколько типов значений и более двух уровней.

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

Кроме того, я должен преобразовать его в json. Используется Json.toJson (newMap), но он, вероятно, имеет несколько типов.

ответ

0

В предположении, что вы всегда имеют комбинацию клавиш «one.two» это будет работать:

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)) 
    } 
}) 

в основном Iam складывание и распространение выходной карты. Первый случай просто проверяет, если для этого ключа уже нет записи. В противном случае, если есть, карта значений будет извлечена и явно добавлена. Он не знает, является ли это лучшим решением. Я думал о версии с zip и другими итеративными подходами, но их не было.

+0

Это работает, но мой случай использования немного отличается, то я думал, что – richs

+0

@Mikel сделал то же самое, но в лучшем образом. Расскажите мне, как ваш случай использования отличается или редактирует вопрос соответствующим образом. Может быть, это поможет. – sascha10000

+0

Я отредактировал вопрос – richs

1

Я хотел бы сделать это

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

Давайте предполагать testMap добавление другого префикса группу для демонстрационных целей:

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

Мы первые разметить на "" и группа префикс и вторично разобрать каждую подкарта раздеться префиксом:

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)) 
Смежные вопросы