从字符串构建字典的最佳方法是什么,如下所示:
"{key1 value1} {key2 value2} {key3 {value with spaces}}"
所以键总是一个没有空格的字符串,但是值是字符串或大括号中的字符串(它有空格)?
你怎么会把它变成:
{'key1': 'value1', 'key2': 'value2', 'key3': 'value with spaces'}
答案 0 :(得分:18)
import re
x="{key1 value1} {key2 value2} {key3 {value with spaces}}"
print dict(re.findall(r"\{(\S+)\s+\{*(.*?)\}+",x))
你可以试试这个。
输出:
{'key3': 'value with spaces', 'key2': 'value2', 'key1': 'value1'}
我们通过re.findall
提取key
及其value
。re.findall
返回包含所有键值对的元组的列表。在列表中使用dict
元组提供了最终答案。 Read more here.
答案 1 :(得分:4)
我无法做得更优雅:
input = "{key1 value1} {key2 value2} {key3 {value with spaces}}"
x = input.split("} {") # creates list with keys and values
y = [i.split(" {") for i in y] # separates the list-values from keys
# create final list with separated keys and values, removing brackets
z = [[i.translate(None,"{").translate(None,"}").split() for i in j] for j in y]
fin = {}
for i in z:
fin[i[0][0]] = i[-1]
非常hacky,但它应该可以胜任。
答案 2 :(得分:2)
假设你的字符串中没有任何东西比你的例子更嵌套,你可以先使用lookahead / lookbehind断言将字符串拆分成你的键值对,寻找模式{{ 1}}(一对括号的末尾和另一对括号的开头。)
SDKROOT
这表示"匹配任何} {
(空白),其前面有>>> str = '{key1 value1} {key2 value2} {key3 {value with spaces}}'
>>> pairs = re.split('(?<=})\s*(?={)', str)
,后面有\s*
,但不包含这些括号比赛本身。&#34;
然后你有你的键值对:
}
可以在{
参数设置为1的空格上拆分,以确保它只在第一个空格上拆分。在这个例子中,我还使用了字符串索引(>>> pairs
['{key1 value1}', '{key2 value2}', '{key3 {value with spaces}}']
)来消除我知道在每对的开头和结尾的花括号。
maxsplit
然后只需检查该值是否包含在花括号中,如果需要,请在将它们放入词典之前将其删除。
如果确保键/值对总是由单个空格字符分隔,那么您可以使用普通的旧字符串拆分。
[1:-1]
答案 3 :(得分:1)
@vks的答案并没有检查平衡的大括号。请尝试以下方法:
>>> x="{key3 {value with spaces} {key4 value4}}"
>>> dict(re.findall(r"\{(\S+)\s+\{*(.*?)\}+",x))
{'key3': 'value with spaces', 'key4': 'value4'}
尝试改为:
>>> dict(map(lambda x:[x[0],x[2]], re.findall(r'\{(\S+)\s+(?P<Brace>\{)?((?(Brace)[^{}]*|[^{}\s]*))(?(Brace)\})\}',x)))
{'key4': 'value4'}
也就是说,它只与具有正确支撑的部分匹配。
(?P<Brace>\{)
保存{
的匹配,后来(?(Brace)\})
只会匹配}
,只有第一个匹配,因此大括号必须匹配对。通过(?(Brace)...|...)
构造,如果\Brace
匹配,则值部分可以包含除大括号([^{}]*
)之外的任何内容,否则不允许空格([^{}\s]*
)。
由于可选括号在正则表达式中匹配,因此在列表中返回,我们需要通过map()
函数从每个列表中提取元素0和2。
正则表达式很容易变得混乱。