Scala 创建不可变的嵌套映射
Scala create immutable nested map
我这里有个情况
我有两个字符串
val keyMap = "anrodiApp,key1;iosApp,key2;xyz,key3"
val tentMap = "androidApp,tenant1; iosApp,tenant1; xyz,tenant2"
所以我想添加的是像这样创建一个嵌套的不可变嵌套映射
tenant1 -> (andoidiApp -> key1, iosApp -> key2),
tenant2 -> (xyz -> key3)
所以基本上是想按租户分组,创建keyMap的map
这是我尝试过的方法,但是是使用我想要的可变映射完成的,有没有办法使用不可变映射创建它
case class TenantSetting() {
val requesterKeyMapping = new mutable.HashMap[String, String]()
}
val requesterKeyMapping = keyMap.split(";")
.map { keyValueList => keyValueList.split(',')
.filter(_.size==2)
.map(keyValuePair => (keyValuePair[0],keyValuePair[1]))
.toMap
}.flatten.toMap
val config = new mutable.HashMap[String, TenantSetting]
tentMap.split(";")
.map { keyValueList => keyValueList.split(',')
.filter(_.size==2)
.map { keyValuePair =>
val requester = keyValuePair[0]
val tenant = keyValuePair[1]
if (!config.contains(tenant)) config.put(tenant, new TenantSetting)
config.get(tenant).get.requesterKeyMapping.put(requester, requesterKeyMapping.get(requester).get)
}
}
将字符串分解为映射的逻辑对于两者来说可以是相同的,因为它是相同的语法。
你对第一个字符串的看法并不完全正确,因为你对拆分结果中的每个字符串而不是数组结果本身应用了过滤器。这也表明您在 keyValuePair 上使用了 [],它的类型为 String
而不是我认为您期望的 Array[String]
。您还需要一个 trim
来处理第二个字符串中的空格。您可能还想 trim 键和值以避免其他空格问题。
此外,在这种情况下,可以使用 collect
更简洁地完成映射和过滤器的组合,如下所示:
How to convert an Array to a Tuple?
使用具有 2 个元素的模式可确保您根据需要过滤掉长度不是 2 的任何内容。
iterator
是为了使 map 和 collect 的组合更有效,只需要对从第一个 split
返回的集合进行一次迭代(参见下面的评论)。
将两个字符串都变成一个映射后,它只需要正确使用 groupBy
来根据相同的键根据第二个映射的值对第一个映射进行分组,以获得您想要的结果。显然,这仅在第二张地图中始终存在相同键的情况下才有效。
def toMap(str: String): Map[String, String] =
str
.split(";")
.iterator
.map(_.trim.split(','))
.collect { case Array(key, value) => (key.trim, value.trim) }
.toMap
val keyMap = toMap("androidApp,key1;iosApp,key2;xyz,key3")
val tentMap = toMap("androidApp,tenant1; iosApp,tenant1; xyz,tenant2")
val finalMap = keyMap.groupBy { case (k, _) => tentMap(k) }
打印出 finalMap 得到:
Map(tenant2 -> Map(xyz -> key3), tenant1 -> Map(androidApp -> key1, iosApp -> key2))
这就是你想要的。
我这里有个情况
我有两个字符串
val keyMap = "anrodiApp,key1;iosApp,key2;xyz,key3"
val tentMap = "androidApp,tenant1; iosApp,tenant1; xyz,tenant2"
所以我想添加的是像这样创建一个嵌套的不可变嵌套映射
tenant1 -> (andoidiApp -> key1, iosApp -> key2),
tenant2 -> (xyz -> key3)
所以基本上是想按租户分组,创建keyMap的map
这是我尝试过的方法,但是是使用我想要的可变映射完成的,有没有办法使用不可变映射创建它
case class TenantSetting() {
val requesterKeyMapping = new mutable.HashMap[String, String]()
}
val requesterKeyMapping = keyMap.split(";")
.map { keyValueList => keyValueList.split(',')
.filter(_.size==2)
.map(keyValuePair => (keyValuePair[0],keyValuePair[1]))
.toMap
}.flatten.toMap
val config = new mutable.HashMap[String, TenantSetting]
tentMap.split(";")
.map { keyValueList => keyValueList.split(',')
.filter(_.size==2)
.map { keyValuePair =>
val requester = keyValuePair[0]
val tenant = keyValuePair[1]
if (!config.contains(tenant)) config.put(tenant, new TenantSetting)
config.get(tenant).get.requesterKeyMapping.put(requester, requesterKeyMapping.get(requester).get)
}
}
将字符串分解为映射的逻辑对于两者来说可以是相同的,因为它是相同的语法。
你对第一个字符串的看法并不完全正确,因为你对拆分结果中的每个字符串而不是数组结果本身应用了过滤器。这也表明您在 keyValuePair 上使用了 [],它的类型为 String
而不是我认为您期望的 Array[String]
。您还需要一个 trim
来处理第二个字符串中的空格。您可能还想 trim 键和值以避免其他空格问题。
此外,在这种情况下,可以使用 collect
更简洁地完成映射和过滤器的组合,如下所示:
How to convert an Array to a Tuple?
使用具有 2 个元素的模式可确保您根据需要过滤掉长度不是 2 的任何内容。
iterator
是为了使 map 和 collect 的组合更有效,只需要对从第一个 split
返回的集合进行一次迭代(参见下面的评论)。
将两个字符串都变成一个映射后,它只需要正确使用 groupBy
来根据相同的键根据第二个映射的值对第一个映射进行分组,以获得您想要的结果。显然,这仅在第二张地图中始终存在相同键的情况下才有效。
def toMap(str: String): Map[String, String] =
str
.split(";")
.iterator
.map(_.trim.split(','))
.collect { case Array(key, value) => (key.trim, value.trim) }
.toMap
val keyMap = toMap("androidApp,key1;iosApp,key2;xyz,key3")
val tentMap = toMap("androidApp,tenant1; iosApp,tenant1; xyz,tenant2")
val finalMap = keyMap.groupBy { case (k, _) => tentMap(k) }
打印出 finalMap 得到:
Map(tenant2 -> Map(xyz -> key3), tenant1 -> Map(androidApp -> key1, iosApp -> key2))
这就是你想要的。