有人可以推荐一种功能性方法来转换下面指定的地图
Map("host.config.autoStart.powerInfo[1].startOrder" -> -1,
"host.config.autoStart.powerInfo[1].startAction" -> "None",
"host.config.autoStart.powerInfo[1].key" -> "vm-XXX",
"host.config.autoStart.powerInfo[0].key" -> "vm-YYY",
"host.config.autoStart.powerInfo[0].startOrder" -> -1,
"host.config.autoStart.powerInfo[0].startAction" -> "None")
到
Map("host.config.autoStart.powerInfo" -> Map(
1 -> Map("startOrder" -> -1,
"startAction" -> "None",
"key" -> "vm-639"),
0 -> Map("startOrder" -> -1,
"startAction" -> "None",
"key" -> "vm-641")))
答案 0 :(得分:3)
一行(长)解决方案:
val R = """([^\[]+)\[(\d+)\]\.(.+)""".r
m.map{ case(R(h,i,k),v) => (h,i,k,v) }.groupBy(_._1).mapValues(_.groupBy(_._2).mapValues{ _.map{case(h,i,k,v) => (k,v)}.toMap} )
res1: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,Any]]] =
Map(host.config.autoStart.powerInfo ->
Map(1 -> Map(startAction -> None,
startOrder -> -1,
key -> vm-XXX),
0 -> Map(key -> vm-YYY,
startAction -> None,
startOrder -> -1)
))
或者写得或多或少可读:
m.map{ case(R(h,i,k),v) => (h,i,k,v) }
.groupBy(_._1).mapValues{ value =>
value.groupBy(_._2).mapValues{ _.map{case(h,i,k,v) => (k,v)}.toMap}
}
答案 1 :(得分:2)
编辑:在代码中添加了一些注释,以便更容易看到正在发生的事情
从我的REPL复制:
scala> val re = """(.+)\[(\d+)\]\.(.+)""".r // Creates a regex to grab the key values
re: scala.util.matching.Regex = (.+)\[(\d+)\]\.(.+)
scala> val m = Map("host.config.autoStart.powerInfo[1].startOrder" -> -1,"host.config.autoStart.powerInfo[1].startAction" -> "None","host.config.autoStart.powerInfo[1].key" -> "vm-XXX","host.config.autoStart.powerInfo[0].key" -> "vm-YYY","host.config.autoStart.powerInfo[0].startOrder" -> -1,"host.config.autoStart.powerInfo[0].startAction" -> "None")
m: scala.collection.immutable.Map[String,Any] = Map(host.config.autoStart.powerInfo[0].key -> vm-YYY, host.config.autoStart.powerInfo[0].startAction -> None, host.config.autoStart.powerInfo[0].startOrder -> -1, host.config.autoStart.powerInfo[1].startAction -> None, host.config.autoStart.powerInfo[1].startOrder -> -1, host.config.autoStart.powerInfo[1].key -> vm-XXX)
scala> val tempList = m map { // Construct a temporary list of Tuples with all relevant values
| case (key, value) => key match {
| case re(p, i, k) => (p, i, k, value)
| }}
tempList: scala.collection.immutable.Iterable[(String, String, String, Any)] = List((host.config.autoStart.powerInfo,0,key,vm-YYY), (host.config.autoStart.powerInfo,0,startAction,None), (host.config.autoStart.powerInfo,0,startOrder,-1), (host.config.autoStart.powerInfo,1,startAction,None), (host.config.autoStart.powerInfo,1,startOrder,-1), (host.config.autoStart.powerInfo,1,key,vm-XXX))
scala> val accumulator = Map[String, Map[String, Map[String, Any]]]()
accumulator: scala.collection.immutable.Map[String,Map[String,Map[String,Any]]] = Map()
scala> val result = tempList.foldLeft(accumulator) {
| case (acc, e) => {
| val middleMap = acc.getOrElse(e._1, Map[String, Map[String, Any]]())
| val innerMap = middleMap.getOrElse(e._2, Map[String, Any]())
| acc + (e._1 -> (middleMap + (e._2 -> (innerMap + (e._3 -> e._4)))))
| }}
result: scala.collection.immutable.Map[String,Map[String,Map[String,Any]]] = Map(host.config.autoStart.powerInfo -> Map(0 -> Map(key -> vm-YYY, startAction -> None, startOrder -> -1), 1 -> Map(startAction -> None, startOrder -> -1, key -> vm-XXX)))