在 Python 中将分号分隔的字符串拆分为字典

Posted

技术标签:

【中文标题】在 Python 中将分号分隔的字符串拆分为字典【英文标题】:Splitting a semicolon-separated string to a dictionary, in Python 【发布时间】:2010-09-16 06:09:39 【问题描述】:

我有一个如下所示的字符串:

"Name1=Value1;Name2=Value2;Name3=Value3"

在 Python 中是否有一个内置的类/函数会接受该字符串并构造一个字典,就好像我已经这样做了:

dict = 
    "Name1": "Value1",
    "Name2": "Value2",
    "Name3": "Value3"

我浏览了可用的模块,但似乎找不到任何匹配的内容。


谢谢,我确实知道如何自己编写相关代码,但由于这种小型解决方案通常是等待发生的雷区(即有人写道:Name1='Value1=2';)等等,所以我通常更喜欢一些预先测试的功能。

那我自己做吧。

【问题讨论】:

你的问题是否需要支持s = r'Name1='Value=2';Name2=Value2;Name3=Value3;Name4="Va\"lue;\n3"'输入(注意:带引号的字符串中的分号,使用反斜杠转义引号,使用\n转义,使用单引号和双引号)? 我的这个问题已经超过 6 年了,涉及这个问题的代码早就被替换了:) 不,它不需要支持引号。我只是想拥有一个预构建的功能,而不是自己编写一些东西。但是,代码早已不复存在。 【参考方案1】:

没有内置函数,但您可以通过生成器理解相当简单地完成此操作:

s= "Name1=Value1;Name2=Value2;Name3=Value3"
dict(item.split("=") for item in s.split(";"))

[编辑]从您的更新中,您表明您可能需要处理引用。这确实使事情复杂化,具体取决于您要查找的确切格式(接受哪些引号字符,哪些转义字符等)。您可能想查看 csv 模块,看看它是否可以覆盖您的格式。这是一个示例:(请注意,此示例的 API 有点笨拙,因为 CSV 旨在遍历一系列记录,因此我进行 .next() 调用只是为了查看第一行。调整为满足您的需求):

>>> s = "Name1='Value=2';Name2=Value2;Name3=Value3"

>>> dict(csv.reader([item], delimiter='=', quotechar="'").next() 
         for item in csv.reader([s], delimiter=';', quotechar="'").next())

'Name2': 'Value2', 'Name3': 'Value3', 'Name1': 'Value1=2'

但是,根据格式的确切结构,您可能需要编写自己的简单解析器。

【讨论】:

代码不处理引用,尝试:s = "Name1='Value;2';Name2=Value2;Name3=Value3"(注意:引用的Name1值中的分号)。 我不知道为什么第二个示例会为我抛出 AttributeError: '_csv.reader' object has no attribute 'next'。当然我做了import csv @Brian 有没有办法将值存储为整数而不是字符串? 怎么能反过来呢@Brain【参考方案2】:

这接近于做你想做的事:

>>> import urlparse
>>> urlparse.parse_qs("Name1=Value1;Name2=Value2;Name3=Value3")
'Name2': ['Value2'], 'Name3': ['Value3'], 'Name1': ['Value1']

【讨论】:

如果输入中有&% 则会中断。 @jfs 但字符串不包含其中任何一个。 @VishalSingh:*** 上的大多数访问者都来自谷歌,因此这里的答案不仅适用于提出问题的原始发帖人。如果我来这里是为了寻找如何在 Python 中将“分号分隔的字符串解析为字典”,那么我的字符串可能包含 &%——至少,值得一提的是,答案没有不适用于此类字符串。【参考方案3】:
easytiger $ cat test.out test.py | sed 's/^/    /'
p_easytiger_quoting:1.84563302994
'Name2': 'Value2', 'Name3': 'Value3', 'Name1': 'Value1'
p_brian:2.30507516861
'Name2': 'Value2', 'Name3': "'Value3'", 'Name1': 'Value1'
p_kyle:7.22536420822
'Name2': ['Value2'], 'Name3': ["'Value3'"], 'Name1': ['Value1']
import timeit
import urlparse

s = "Name1=Value1;Name2=Value2;Name3='Value3'"

def p_easytiger_quoting(s):
    d = 
    s = s.replace("'", "")
    for x in s.split(';'):
        k, v = x.split('=')
        d[k] = v
    return d


def p_brian(s):
    return dict(item.split("=") for item in s.split(";"))

def p_kyle(s):
    return urlparse.parse_qs(s)



print "p_easytiger_quoting:" + str(timeit.timeit(lambda: p_easytiger_quoting(s)))
print p_easytiger_quoting(s)


print "p_brian:" + str(timeit.timeit(lambda: p_brian(s)))
print p_brian(s)

print "p_kyle:" + str(timeit.timeit(lambda: p_kyle(s)))
print p_kyle(s)

【讨论】:

这不能回答问题,因为它不处理引用。尝试s = "Name1='Value1=2';Name2=Value2" and csv`(如布莱恩接受的答案)或parse_qs(如凯尔的)会得到正确的,而你的会提出ValueError。 OP 特别指出“如此小的解决方案通常是等待发生的雷区”,这就是他想要一个内置或其他经过良好测试的解决方案的原因,他给出了一个会破坏您的代码的示例。 啊,我没看到。仍然。在迭代发生之前预解析主字符串中的内容并调用替换函数数千次,它仍然比所有解决方案都要快。我会更新 我不确定你将如何准备它。但即使你这样做,这似乎正是 OP 在一个简单的解决方案中所害怕的。你确定前面没有其他地雷吗?你能证明它让 OP 满意吗? 好的,既然我已经看到了你的编辑……首先,s.replace 根本没有做任何事情;它只是返回一个您忽略的新字符串。其次,即使你做对了(s = s.replace…),也不能解决问题,它只是在上面添加了一个新问题。在我的示例或 OP 上尝试一下。 规范明确包括处理他在问题Name='Value1=2'; 中提到的示例输入。而且您的代码无法处理它。而且我不确定你会如何清理它而不以某种方式解析它,这将与 urlparsecsv 首先一样慢。【参考方案4】:

如果您的 Value1、Value2 只是实际值的占位符,您还可以将 dict() 函数与 eval() 结合使用。

>>> s= "Name1=1;Name2=2;Name3='string'"
>>> print eval('dict('+s.replace(';',',')+')')
'Name2: 2, 'Name3': 'string', 'Name1': 1

这是因为dict() 函数理解语法dict(Name1=1, Name2=2,Name3='string')。字符串中的空格(例如,在每个分号之后)被忽略。但请注意,字符串值确实需要引用。

【讨论】:

谢谢,支持 string.replace 效果很好。不知道为什么我不能分开。我在 tc 框上做了 i = textcontrol.GetValue(),然后 o = i.split(';') 但没有输出一个字符串,只是抱怨格式,不像替换。 s.replace(';'-based 解决方案如果在引用值中有 ;,则会中断。 eval is evil 在这种情况下是不必要的。【参考方案5】:

可以简单地通过字符串连接和列表推导来完成

",".join(["%s=%s" % x for x in d.items()])

>>d = 'a':1, 'b':2
>>','.join(['%s=%s'%x for x in d.items()])
>>'a=1,b=2'

【讨论】:

【参考方案6】:
s1 = "Name1=Value1;Name2=Value2;Name3=Value3"

dict(map(lambda x: x.split('='), s1.split(';')))

【讨论】:

以上是关于在 Python 中将分号分隔的字符串拆分为字典的主要内容,如果未能解决你的问题,请参考以下文章

如何在awk中将分隔字符串拆分为数组?

在Oracle中将连字符分隔的字符串拆分为行

仅当分隔符存在于字符串上时,才使用两个不同的分隔符拆分 Python 字典中的字符串

如何在 C++ 中将空格分隔的字符串拆分为多个字符串?

Python:按分隔符列表拆分字符串

拆分多列分号分隔的字符串并创建记录