我有一个字符串
"{a:'b', c:'d',e:''}"
请注意,字典条目的键不加引号,因此previous question中建议的简单eval("{a:'b', c:'d',e:''}")
不起作用。
将此字符串转换为字典最方便的方法是什么?
{'a':'b', 'c':'d', 'e':''}
答案 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
参数,identdict
为globals
。 eval
将从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
,因此您可以使用填充值,其灵感来自:
答案 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
答案无法处理诸如if
或for
之类的键。
相反,我们可以将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': ' : , '}