将子串转换为dict

ano*_*n01 9 python string

寻找一种优雅的方法将子字符串列表和它们之间的文本转换为字典中的键值对.例:

s = 'k1:some text k2:more text k3:and still more'
key_list = ['k1','k2','k3']
(missing code)
# s_dict = {'k1':'some text', 'k2':'more text', 'k3':'and still more'}  
Run Code Online (Sandbox Code Playgroud)

这是可以使用str.find()等解决的,但我知道有一个比我一起攻击的更好的解决方案.

cs9*_*s95 13

选项1
如果键没有空格或冒号,您可以使用dict+ re.findall(import re,第一个)简化解决方案:

>>> dict(re.findall('(\S+):(.*?)(?=\s\S+:|$)', s))
{'k1': 'some text', 'k2': 'more text', 'k3': 'and still more'}
Run Code Online (Sandbox Code Playgroud)

只有冒号(:)的位置决定了键/值的匹配方式.

细节

(\S+)   # match the key (anything that is not a space)
:       # colon (not matched)
(.*?)   # non-greedy match - one or more characters - this matches the value 
(?=     # use lookahead to determine when to stop matching the value
\s      # space
\S+:    # anything that is not a space followed by a colon 
|       # regex OR
$)      # EOL
Run Code Online (Sandbox Code Playgroud)

请注意,此代码假定问题中显示的结构.它将在具有无效结构的字符串上失败.


选项2
看看ma,没有正则表达式......
这与上面的假设相同.

  1. 拆分冒号(:)
  2. 除了第一个和最后一个元素之外的所有元素都需要在空间上再次分割(以分隔键和值)
  3. 压缩相邻元素,并转换为字典

v = s.split(':')
v[1:-1] = [j for i in v[1:-1] for j in i.rsplit(None, 1)]

dict(zip(v[::2], v[1::2]))
{'k1': 'some text', 'k2': 'more text', 'k3': 'and still more'}
Run Code Online (Sandbox Code Playgroud)

  • 令人印象深刻."正则表达式"是否会使你的眼睛流血,或者随着时间的推移会变得更好?:) (2认同)

Jea*_*bre 7

如果键中没有空格或冒号,您可以:

  • 按照alpha分割后跟冒号来获取代币
  • 拉链半切片在词典理解中重建词典

像这样:

import re,itertools
s = 'k1:some text k2:more text k3:and still more'
toks = [x for x in re.split("(\w+):",s) if x]  # we need to filter off empty tokens
# toks => ['k1', 'some text ', 'k2', 'more text ', 'k3', 'and still more']
d = {k:v for k,v in zip(itertools.islice(toks,None,None,2),itertools.islice(toks,1,None,2))}
print(d)
Run Code Online (Sandbox Code Playgroud)

结果:

{'k2': 'more text ', 'k1': 'some text ', 'k3': 'and still more'}
Run Code Online (Sandbox Code Playgroud)

使用itertools.isliceavoids来创建子列表就像toks[::2]那样做


Rom*_*est 5

另一个正则表达式魔法,用于在键/值对上拆分输入字符串:

import re

s = 'k1:some text k2:more text k3:and still more'
pat = re.compile(r'\s+(?=\w+:)')
result = dict(i.split(':') for i in pat.split(s))

print(result)
Run Code Online (Sandbox Code Playgroud)

输出:

{'k1': 'some text', 'k2': 'more text', 'k3': 'and still more'}
Run Code Online (Sandbox Code Playgroud)
  • re.compile()在单个程序中多次使用表达式时,使用和保存生成的正则表达式对象以便重用更有效
  • \s+(?=\w+:)- \s+如果后面跟一个"key"(一个\w+带冒号的单词),用空格字符分隔输入字符串的关键模式:.
    (?=...) - 代表前瞻性的积极主张