将字符串解析为元组列表

3

输入:'(标记名1,标记值1),(标记名2,标记值2),(标记名3,标记值3),(标记名称4,标记值4)'

输出:[("标记名1", "标记值1"),("标记名2", "标记值2"),("标记名3", "标记值3"),("标记名称4", "标记值4")]

我有一个解决方案,但只在输入中每个元素都包含引号时有效:"tagname1", "tagvalue1"

import ast
ast.literal_eval(input_string)

在我的情况下,我收到以下错误:ValueError: malformed string。有没有解决方案来让它工作(请注意空格)?
4个回答

11

尝试使用正则表达式的另一种方法:

>>> import re
>>> s = '(tagname1, tagvalue1),(tagname2,tagvalue2), ( tagname3, tagvalue3 ), (tag name4,tag value4)'
>>> e = '\(\s?(.*?)\s?,\s?(.*?)\s?\)'
>>> re.findall(e, s)
[('tagname1', 'tagvalue1'), ('tagname2', 'tagvalue2'), ('tagname3', 'tagvalue3'), ('tag name4', 'tag value4')]

算了,我的解决方案显然是错误的。这个完美! - Adam Smith
@Chris_Rands 谢谢,已修复。 - Burhan Khalid
它仍然无法处理多个空格。 - randomir

1
这里有一个可以处理多个空格(非单词字符)的re.findall变体:
>>> import re
>>> s = '(tagname1, tagvalue1  ),  ( tagname2 ,   tagvalue2   ), (      tagname3, tagvalue3 ), (tag name4,   tag value4   )'
>>> re.findall('\(\W*([\w\s]*?)\W*,\W*([\w\s]*?)\W*\)', s)
[('tagname1', 'tagvalue1'), ('tagname2', 'tagvalue2'), ('tagname3', 'tagvalue3'), ('tag name4', 'tag value4')]

注意,在单词字符(包括空格)后面加上非贪婪闭合符(重复限定符)[\w\s]*?。这确保了每个标签名称/值的所有单词都被捕获,但不包括所有前导和尾随空格。这就是为什么上面正确捕获了"tag value4"

标签名称4,标签值4 - 在输出中缺失 - GhitaB
我错过了那个情况(中间带空格)。已经修复。现在它将删除前导和尾随空格,但保留中间的空格。 - randomir
1
太棒了。正则表达式对我来说就像巫术一样。:D - GhitaB

1

除了Burhan提出的方法,还可以利用反向引用的功能。您可以在这里阅读有关反向引用的更多信息。

import re

# Input string
string = '(tagname1, tagvalue1),(tagname2,tagvalue2), ( tagname3, tagvalue3 ), (tag name4,tag value4)'

# Regular expression pattern 
pattern = re.compile(r"\(([a-z0-9 ]+), ?([a-z0-9 ]+)\)", re.I)

list_of_tupples = []
for matched_object in pattern.finditer(string):
    list_of_tupples.append((matched_object.group(1), matched_object.group(2)))

您可以在这里看到正则表达式演示。

注意:

我还使用了pattern.finditter(),因为这样你可以遍历文本中所有模式发现。来自re.finditer文档:

re.finditer(pattern, string, flags=0)返回一个迭代器,它在字符串中为RE模式生成MatchObject实例的所有非重叠匹配项。该字符串从左到右扫描,并按找到的顺序返回匹配项。除非它们接触到另一个匹配的开头,否则空匹配将包含在结果中。


1
另一种非正则表达式的方法:
def string_to_tuples(s):
    def tuple_strip(s):  # Wrapper to pass to map
        return s.strip(" ()")

    sl = map(tuple_strip, s.split(","))
    return zip(sl[::2], sl[1::2])

这将产生:

>>> string_to_tuples('(tagname1, tagvalue1),(tagname2,tagvalue2), ( tagname3, tagvalue3 ), (tag name4,tag value4)')
[('tagname1', 'tagvalue1'), ('tagname2', 'tagvalue2'), ('tagname3', 'tagvalue3'), ('tag name4', 'tag value4')]

只要标签不以(空格)、()开始或结束,并且不包含任何,,就可以正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接