如何将带有不带引号的键的字符串转换为Python中的dict

How to turn a string with unquoted keys into a dict in Python

本问题已经有最佳答案,请猛点这里访问。

我有根绳子

1
"{a:'b', c:'d',e:''}"

请不要将字典条目的键未加引号,因此前面问题中建议的简单eval("{a:'b', c:'d',e:''}")不起作用。

将这个字符串转换成字典最方便的方法是什么?

1
{'a':'b', 'c':'d', 'e':''}


如果这是来自可信来源(不要将其用于一般用户输入,因为eval是不安全的;但是,如果您从潜在的恶意用户那里获得输入,那么您应该使用json格式和json模块,而不是使用eval和一个技巧。

1
2
3
4
5
6
7
8
source ="""{e: '', a: 'b', c: 'd'}"""

class identdict(dict):
    def __missing__(self, key):
        return key

d = eval(source, identdict())
print(d)

印刷品

1
{'a': 'b', 'c': 'd', 'e': ''}

我们创建了一个新的字典子类identdict,它定义了神奇的方法__missing__。调用此方法查找字典中缺少的键。在这种情况下,我们只返回键,所以字典将键映射到它们自己。然后,用identdict实例作为globals论证,得出sourceeval的结论。eval将从globals映射中查找变量的值;由于它是identdict映射,因此现在访问的每个变量的值都很方便成为变量的名称。

适用于更复杂的字符串作为值,以及任何合适的python文本语法。


根据您要分析的内容的复杂性,这可能有效:

1
2
3
4
5
s ="{a:'b', c:'d',e:''}"
d = dict([
    (x.split(':')[0].strip(), x.split(':')[1].strip("'"))
    for x in s.strip("{}").split(',')
])


警告:如果您在"字典"中间有一个空字符串的键映射,则此方法将无法按预期工作。我不会删除此答案,因为我认为此方法可能仍然可用。

这可能比威尔的答案更一般,不过,它仍然取决于您要解析的内容的确切结构。如果您的键、值对将由字母数字单词组成,那么您应该很好。

1
2
3
4
5
6
7
8
9
10
11
12
In [3]: import re

In [4]: import itertools

In [5]: my_string ="{a:'b', c:'d',e:''}"

In [6]: temp = re.findall(r"\w", my_string)

In [7]: temp = itertools.zip_longest(temp[0::2], temp[1::2], fillvalue ="")

In [8]: dict(temp)
Out[8]: {'a': 'b', 'c': 'd', 'e': ''}

如果您想知道zip函数发生了什么,请参见以下问题:

将列表中的每对元素收集到Python中的元组中

我使用了itertools.zip_longest,因此您可以使用填充值,灵感来自:

来自单个列表的对


1
2
3
import re
str="{a:'b', c:'d',e:''}"
dict([i.replace("'","").split(":") for i in re.findall(r"(\w+\:'.*?')",str)])

您可以通过使用JSON包来实现这一点;

1
2
3
4
import json
s = '{"a":"b","c":"d","e":"f"}'
my_dict = json.loads(s)
print type(my_dict)


你也可以这样做,即使它不漂亮。它确实取决于字符串的结构。你还需要评估其他类型的字串听写吗?

1
2
3
4
5
6
7
8
9
10
11
12
string ="{a:'b', c:'d',e:''}"[1:-1].split(",")

d = {}
for s in string:
    s = s.strip()
    key, value = s[0], s[-2]
    if value.isalpha():
        d[key] = value
    else:
        d[key] = ''

print(d)

输出:

1
{'e': '', 'a': 'b', 'c': 'd'}