将字符串元组转换为dict

时间:2017-02-09 12:39:29

标签: python regex string dictionary replace

我的字符串格式不正确:

a = '(a,1.0),(b,6.0),(c,10.0)'

我需要dict

d = {'a':1.0, 'b':6.0, 'c':10.0}

我试试:

print (ast.literal_eval(a))
#ValueError: malformed node or string: <_ast.Name object at 0x000000000F67E828>

然后我尝试将字符替换为'string dict',这很丑陋并且不起作用:

b = a.replace(',(','|{').replace(',',' : ')
     .replace('|',', ').replace('(','{').replace(')','}')
print (b)
{a : 1.0}, {b : 6.0}, {c : 10.0}

print (ast.literal_eval(b))
#ValueError: malformed node or string: <_ast.Name object at 0x000000000C2EA588>

你做什么的?有什么遗失?可以使用regex吗?

4 个答案:

答案 0 :(得分:4)

如果您的字符串采用此格式,则无需正则表达式。

>>> a = '(a,1.0),(b,6.0),(c,10.0)'
>>> d = dict([x.split(',') for x in a[1:-1].split('),(')])
>>> print(d)
{'c': '10.0', 'a': '1.0', 'b': '6.0'}

我们删除了第一个开放的parantheses和最后的结束parantheses,通过分割),(来获得键值对。然后可以在逗号上拆分对。

要转换为浮动,列表理解会变得更长一些:

d = dict([(a, float(b)) for (a, b) in [x.split(',') for x in a[1:-1].split('),(')]])

答案 1 :(得分:3)

如果括号内总是有2个以逗号分隔的值,而第二个是浮点类型,则可以使用

import re
s = '(a,1.0),(b,6.0),(c,10.0)'
print(dict(map(lambda (w, m): (w, float(m)), [(x, y) for x, y in re.findall(r'\(([^),]+),([^)]*)\)', s) ])))

请参阅Python demo和(非常通用的)regex demo。此模式只匹配(,然后匹配除逗号以外的0 +字符和)捕获到组1,然后匹配逗号,然后匹配)以外的任何0 +字符(捕获)进入第2组)和)

由于上述模式适用于预先验证的数据,因此可以限制当前数据的正则表达式

r'\((\w+),(\d*\.?\d+)\)'

请参阅regex demo

<强>详情:

  • \( - 文字(
  • (\w+) - 捕获第1组:一个或多个字(字母/数字/ _)字符
  • , - 逗号
  • (\d*\.?\d+) - 一个常见的整数/浮动正则表达式:零个或多个数字,一个可选的.(十进制分隔符)和一个以上的数字
  • \) - 一个字面右括号。

答案 2 :(得分:3)

鉴于字符串具有上述格式,您可以使用 backrefs 进行正则表达式替换:

import re

a = '(a,1.0),(b,6.0),(c,10.0)'
a_fix = re.sub(r'\((\w+),', r"('\1',",a)

因此,您需要查找模式(x,x一系列\w s,然后将其替换为('x',。结果是:

# result
a_fix == "('a',1.0),('b',6.0),('c',10.0)"

然后解析a_fix并将其转换为dict

result = dict(ast.literal_eval(a_fix))

结果当时:

>>> dict(ast.literal_eval(a_fix))
{'b': 6.0, 'c': 10.0, 'a': 1.0}

答案 3 :(得分:2)

eval()不起作用的原因是a, b, c未定义,我们可以使用它来定义那些字符串形式,eval将使用该字符串形式

In [11]: text = '(a,1.0),(b,6.0),(c,10.0)'

In [12]: a, b, c = 'a', 'b', 'c'

In [13]: eval(text)
Out[13]: (('a', 1.0), ('b', 6.0), ('c', 10.0))

In [14]: dict(eval(text))
Out[14]: {'a': 1.0, 'b': 6.0, 'c': 10.0}

以正则表达式方式执行此操作:

In [21]: re.sub(r'\((.+?),', r'("\1",', text)
Out[21]: '("a",1.0),("b",6.0),("c",10.0)'
In [22]: eval(_)
Out[22]: (('a', 1.0), ('b', 6.0), ('c', 10.0))

In [23]: dict(_)
Out[23]: {'a': 1.0, 'b': 6.0, 'c': 10.0}