Python 解析字符串列表

3 投票
6 回答
11872 浏览
提问于 2025-04-16 15:40

我有一串字符串,我想找像这样的行:

键: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())

撰写回答