2016-07-14 34 views
1

给定一阶串,其具有键 - 值对的集合(具有类型键 - 值对的顺序不是固定的,而不是固定的键 - 值对的数量):快速的方式来提取阶字符串标记

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" 

我正在寻找一种功能性的方式来做到这一点的操作。

回答

5

如果你的键值对没有嵌套的括号,你可以使用正则表达式用逗号+空格未遵循比(其他任何字符,)高达)分裂:

""", (?![^()]*\))""".r 

regex demo

说明

  • , - 匹配逗号且仅当加上一个空格...
  • (?![^()]*\)) - 没有随着非)和非)(0次或更多次),然后用文字)(也就是说,如果不按照与东西+ ))。

如果你想尝试与匹配的方法:

"""([^=:]*):\s*(.*?),?\s*(?=$|\w+:)""".r 

this demo

详细

  • ([^=:]*) - 第1个捕获0+字符比=其他和:(也许,一个*应与+被替换,因为密钥不能为空)
  • :\s* - 任何字符,但换行符尽可能少(第2组,(.*?)),其随后与可选的 - 与0+空格
  • (.*?),?\s*冒号,和0+空格...
  • (?=$|\w+:) - 后面跟着字符串结尾或1 +单词字符和冒号。
+1

完美!这太棒了! –