如何将格式错误的字符串转换为字典?

时间:2013-01-09 13:50:20

标签: python string dictionary

我有一个字符串s(请注意,ab未用引号括起来,因此无法直接将其评估为dict) :

s = '{a:1,b:2}'

我希望将此变量转换为dict,如下所示:

{'a':1,'b':2}

我该怎么做?

5 个答案:

答案 0 :(得分:5)

这适用于您的示例:

import ast
def elem_splitter(s):
    return s.split(':',1)

s = '{a:1,b:2}'
s_no_braces = s.strip()[1:-1] #s.translate(None,'{}') is more elegant, but can fail if you can have strings with '{' or '}' enclosed.
elements = (elem_splitter(ss) for ss in s_no_braces.split(','))
d = dict((k,ast.literal_eval(v)) for k,v in elements)

请注意,如果您的字符串格式为:

,则会失败
'{s:"foo,bar",ss:2}'  #comma in string is a problem for this algorithm

或:

'{s,ss:1,v:2}' 

但它会传递一个字符串,如:

'{s ss:1,v:2}' #{"s ss":1, "v":2}

您可能还想稍微修改elem_splitter,具体取决于您的需求:

def elem_splitter(s):
    k,v = s.split(':',1)
    return k.strip(),v # maybe `v.strip() also?`

*其他人可能会使用更多的ast模块做一个更好的例子,但我不知道它的内部结构非常好,所以我怀疑我是否有时间做出这个答案。

答案 1 :(得分:2)

由于你的字符串格式错误,因为json和Python都是dict所以你们都不能使用json.loads而不是ast.literal_eval来直接转换数据。

在这种特殊情况下,你必须通过了解输入数据手动将其翻译成Python字典

>>> foo = '{a:1,b:2}'
>>> dict(e.split(":") for e in foo.translate(None,"{}").split(","))
{'a': '1', 'b': '2'}

由Tim更新,我的短视我错过了值应该是整数的事实,这是一个替代实现

>>> {k: int(v) for e in foo.translate(None,"{}").split(",") 
     for k, v in [e.split(":")]}
{'a': 1, 'b': 2}

答案 2 :(得分:2)

import re,ast
regex = re.compile('([a-z])')
ast.literal_eval(regex.sub(r'"\1"', s))

<强>出:

{'a': 1, 'b': 2}

编辑: 如果碰巧有类似{foo1:1,bar:2}的东西,请在正则表达式中添加一个额外的捕获组:

regex = re.compile('(\w+)(:)')
ast.literal_eval(regex.sub(r'"\1"\2', s))

答案 3 :(得分:0)

你可以这样做:

s = "{a:1,b:2}"
content = s[s.index("{")+1:s.index("}")]
to_int = lambda x: int(x) if x.isdigit() else x
d = dict((to_int(i) for i in pair.split(":", 1)) for pair in content.split(","))

为简单起见,如果字符串不包含有效规范,我省略了异常处理,并且此版本也不会删除您可能需要的空格。如果你喜欢的解释是键总是一个字符串而且值总是int,那么它就更容易了:

s = "{a:1,b:2}"
content = s[s.index("{")+1:s.index("}")]
d = dict((int(pair[0]), pair[1].strip()) for pair in content.split(","))

作为奖励,此版本还会从密钥中删除空白以显示它的简单性。

答案 4 :(得分:-2)

import simplejson
s = '{a:1,b:2}'
a = simplejson.loads(s)
print a