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

时间:2016-06-21 05:01:10

标签: python

我有一个字符串

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

请注意,字典条目的键不加引号,因此previous question中建议的简单eval("{a:'b', c:'d',e:''}")不起作用。

将此字符串转换为字典最方便的方法是什么?

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

7 个答案:

答案 0 :(得分:4)

如果这是来自受信任的来源(不要将此用作一般用户输入,请{?3}};但如果您从潜在恶意中获取输入,请再次使用如果用户使用JSON格式而不是eval is not secure,则可以使用eval进行操作。

source = """{e: '', a: 'b', c: 'd'}"""

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

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

打印

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

这是如何工作的,我们创建了一个新的字典子类identdict来定义魔术方法__missing__。调用此方法以查找字典中缺少的键。在这种情况下,我们只返回键,因此字典将键映射到自己。然后,使用source实例作为eval参数,identdictglobalseval将从globals映射中查找变量的值;因为它是identdict,所以每个访问的变量的值现在都是变量的名称。

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

答案 1 :(得分:3)

根据您正在解析的内容的复杂程度,这可能有效:

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

答案 2 :(得分:1)

警告如果您在"字典中间有一个空字符串的键映射,则此方法将无法正常工作。"我不会删除这个答案,因为我认为这种方法可能仍然可以挽救。

这可能比威尔的答案更为通用,但它仍然取决于你要解析的内容的确切结构。如果您的键值对包含字母数字,那么您应该没问题。

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功能发生了什么,请参阅以下问题:

Collect every pair of elements from a list into tuples in Python

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

Pairs from single list

答案 3 :(得分:0)

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

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)

输出:

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

答案 4 :(得分:0)

你可以通过使用json包来实现这一点;

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

手动解析容易出错且难以通用,并且当键为Python关键字时,基于eval的方法会失败。如果值包含空格,逗号或冒号,则当前接受的答案会中断,并且eval答案无法处理诸如iffor之类的键。

相反,我们可以将tokenize输入作为一系列Python令牌并将NAME令牌替换为STRING令牌,然后取消令牌化以构建有效的字典文字。从那里,我们可以致电ast.literal_eval

import ast
import io
import tokenize

def parse(x):
    tokens = tokenize.generate_tokens(io.StringIO(x).readline)
    modified_tokens = (
        (tokenize.STRING, repr(token.string)) if token.type == tokenize.NAME else token[:2]
        for token in tokens)

    fixed_input = tokenize.untokenize(modified_tokens)

    return ast.literal_eval(fixed_input)

然后parse("{a:'b', c:'d',e:''}") == {'a':'b', 'c':'d', 'e':''},关键字作为键或值中的特殊字符不会出现问题:

>>> parse('{a: 2, if: 3}')
{'a': 2, 'if': 3}
>>> parse("{c: ' : , '}")
{'c': ' : , '}