给定一个scala字符串,其中包含一组键值对(键值对的类型顺序不固定,键值对的数量不固定):
val s = "key1: val1, key2: (val2.1, val2.2, val2.3), key3: (), key4: val4"
我需要把它们拉成一个不可变的地图,如:
Map("key1" -> "val1",
"key2" -> "(val2.1, val2.2, val2.3)",
"key3" -> "()",
"key4" -> "val4")
我试过这个:
val kvMap = s.split(", ").map(_.split(": ")).map(t => t(0) -> t(1)).toMap
但是失败了,因为在括号中和键值对之间使用相同的分隔符(逗号)。
我可以使用迭代使用堆栈但是想避免这种情况。
我也尝试过写一个可以帮助我做到这一点的正则表达式,但可以让它只能用于1对:
scala> val MyPattern = "([^=]*):(.*)".r
Pattern: scala.util.matching.Regex = ([^=]*):(.*)
^
scala> val MyPattern(k, v) = "key: value"
k: String = key
v: String = " value"
我正在寻找一种功能性的方法来完成这项操作。
答案 0 :(得分:5)
如果你的键值对没有嵌套的括号,你可以使用正则表达式用逗号+空格分割,除了(
和)
以外的任何字符都不跟{{{ 1}}:
)
请参阅regex demo
<强>解释强>:
""", (?![^()]*\))""".r
- 只有在...... ,
- 未跟随非(?![^()]*\))
和非)
(0次或更多次)后跟文字)
(即,如果没有跟随某事+ )
)。如果您想尝试匹配的方法:
)
请参阅this demo
<强>详情:
"""([^=:]*):\s*(.*?),?\s*(?=$|\w+:)""".r
- 第1组捕获除([^=:]*)
和=
以外的0 +个字符(可能:
应替换为*
,因为密钥不能是空的)+
- 一个0 +空格的冒号:\s*
- 任意字符,但换行符尽可能少(第2组,(.*?),?\s*
),后跟可选的(.*?)
和0+空格...... ,
- 跟随字符串结尾或1个单词字符和冒号。