Python 解析字符串列表
我有一串字符串,我想找像这样的行:
键:af12d9 索引:0 字段1:1234 字段2:1234 字段3:-10
找到这样的行后,我想把每一行存储为一个字典,比如 {'key' : af12d9, 'index' : 0, 'field 1' : .... },然后把这个字典放到一个列表里,这样我就会有一个字典的列表。
我已经能做到这一点,代码如下:
listconfig = []
for line in list_of_strings:
matched = findall("(Key:[\s]*[0-9A-Fa-f]+[\s]*)|(Index:[\s]*[0-9]+[\s]*)|(Field 1:[\s]*[0-9]+[\s]*)|(Field 2:[\s]*[0-9]+[\s]*)|(Field 3:[\s]*[-+]?[0-9]+[\s]*)", line)
if matched:
listconfig += [dict(map(lambda pair: (pair[0].strip().lower(), pair[1].strip().lower()),
map(lambda line: line[0].split(':'),
[filter(lambda x: x, group) for group in matched])))]
我只是想知道有没有更好的方法(更简短和高效)来做到这一点,因为我觉得 findall 每个字符串会搜索5次。(对吗?因为它返回一个包含5个元组的列表。)
谢谢。
解决方案:
好的,在brandizzi的帮助下,我找到了这个问题的答案。
解决方案:
listconfig = []
for line in list_of_strings:
matched = re.search(r"Key:[\s]*(?P<key>[0-9A-Fa-f]+)[\s]*" \
r"(Index:[\s]*(?P<index>[0-9]+)[\s]*)?" \
r"(Field 1:[\s]*(?P<field_1>[0-9]+)[\s]*)?" \
r"(Field 2:[\s]*(?P<field_2>[0-9 A-Za-z]+)[\s]*)?" \
r"(Field 3:[\s]*(?P<field_3>[-+]?[0-9]+)[\s]*)?", line)
if matched:
print matched.groupdict()
listconfig.append(matched.groupdict())
6 个回答
0
import re
str_list = "Key: af12d9 Index: 0 Field 1: 1234 Field 2: 1234 Ring Field 3: -10"
results = {}
for match in re.findall("(.*?):\ (.*?)\ ", str_list+' '):
results[match[0]] = match[1]
当然可以!请把你想要翻译的内容发给我,我会帮你把它变得更简单易懂。
5
首先,你的正则表达式似乎有点问题。Key
字段的值应该可以包含 f
,对吧?所以它的分组不应该是 ([0-9A-Ea-e]+)
,而应该是 ([0-9A-Fa-f]+)
。另外,在处理正则表达式时,最好在字符串前加个 r
,这样可以避免 \
转义字符的问题。(如果你不明白为什么要这样做,可以看看原始字符串)
接下来,我来讲讲我解决这个问题的方法。首先,我会创建一个没有管道符的正则表达式:
>>> regex = r"(Key):[\s]*([0-9A-Fa-f]+)[\s]*" \
... r"(Index):[\s]*([0-9]+)[\s]*" \
... r"(Field 1):[\s]*([0-9]+)[\s]*" \
... r"(Field 2):[\s]*([0-9 A-Za-z]+)[\s]*" \
... r"(Field 3):[\s]*([-+]?[0-9]+)[\s]*"
这样一来,findall()
就会返回整行中找到的分组的一个元组。在这个元组中,每个键后面都有它的值:
>>> re.findall(regex, line)
[('Key', 'af12d9', 'Index', '0', 'Field 1', '1234', 'Field 2', '1234 Ring ', 'Field 3', '-10')]
所以我得到了这个元组……
>>> found = re.findall(regex, line)[0]
>>> found
('Key', 'af12d9', 'Index', '0', 'Field 1', '1234', 'Field 2', '1234 Ring ', 'Field 3', '-10')
……然后通过切片我只提取出键……
>>> found[::2]
('Key', 'Index', 'Field 1', 'Field 2', 'Field 3')
……也只提取出值:
>>> found[1::2]
('af12d9', '0', '1234', '1234 Ring ', '-10')
接着,我用zip()
函数创建一个包含键和对应值的元组列表:
>>> zip(found[::2], found[1::2])
[('Key', 'af12d9'), ('Index', '0'), ('Field 1', '1234'), ('Field 2', '1234 Ring '), ('Field 3', '-10')]
最后的高潮是把这个元组列表传给 dict()
构造函数:
>>> dict(zip(found[::2], found[1::2]))
{'Field 3': '-10', 'Index': '0', 'Field 1': '1234', 'Key': 'af12d9', 'Field 2': '1234 Ring '}
我觉得这个解决方案是最好的,不过在某种意义上这也是个主观问题。希望对你有帮助 :)
1
好的,在brandizzi的帮助下,我找到了这个问题的答案。
解决方案:
listconfig = []
for line in list_of_strings:
matched = re.search(r"Key:[\s]*(?P<key>[0-9A-Fa-f]+)[\s]*" \
r"(Index:[\s]*(?P<index>[0-9]+)[\s]*)?" \
r"(Field 1:[\s]*(?P<field_1>[0-9]+)[\s]*)?" \
r"(Field 2:[\s]*(?P<field_2>[0-9 A-Za-z]+)[\s]*)?" \
r"(Field 3:[\s]*(?P<field_3>[-+]?[0-9]+)[\s]*)?", line)
if matched:
print matched.groupdict()
listconfig.append(matched.groupdict())