15

我遇到过这个问题几次,似乎无法找出一个简单的解决方案。 说我有一个字符串将字符串转换为字典在Python中使用列表理解

string = "a=0 b=1 c=3" 

我想将其转换成具有,b和c是所述键和0,1和3被它们各自的值的字典(转换为int)。很显然,我可以这样做:

list = string.split() 
    dic = {} 
    for entry in list: 
     key, val = entry.split('=') 
     dic[key] = int(val) 

但我真的不喜欢那个for循环,它似乎很简单,你应该能够将其转换为某种形式的名单理解的表达。这适用于val可以是字符串的稍微简单的情况。

dic = dict([entry.split('=') for entry in list]) 

但是,我需要将val快速转换为int,并且执行类似这样的操作在语法上是不正确的。

dic = dict([[entry[0], int(entry[1])] for entry.split('=') in list]) 

所以我的问题是:是否有消除使用列表理解循环的方法吗?如果没有,是否有一些内置的python方法可以为我做到这一点?

+0

注:请不要使用内置函数作为变量名('string','list'等) – 2010-09-03 04:48:59

回答

29

你的意思是?

>>> dict((n,int(v)) for n,v in (a.split('=') for a in string.split())) 
{'a': 0, 'c': 3, 'b': 1} 
+4

虽然这很酷,我觉得我更喜欢原来的问题的版本,从长远代码维护的观点。原始问题中的代码清晰明了,上面需要数十秒时间才能完成。 – 2009-08-07 21:28:37

+1

@Bryan Oakley:我同意。问题(“是否有一种方法可以消除使用列表理解的for循环”)有一个答案。但是,答案可能不是他们真正想要的。 – 2009-08-07 21:40:57

+1

是的,这就是我一直在寻找的。谢谢。 @Bryan:我开始认为保持循环可能是一个好主意。尽管如此,至少现在我知道如何做到这一点。 – Pavel 2009-08-08 01:14:08

1
from cgi import parse_qsl 
text = "a=0 b=1 c=3" 
dic = dict((k, int(v)) for k, v in parse_qsl(text.replace(' ', '&'))) 
print dic 

打印

{'a': 0, 'c': 3, 'b': 1} 
+0

不错......... 15。 – 2009-08-07 19:38:58

-3

我喜欢美国洛特的解决方案,但我想出了另一种可能性。
既然你已经有一个字符串类似不知为何,你会写的方式,你可以使其适应Python语法,然后eval()函数吧:)

import re 
string = "a=0 b=1 c=3" 
string2 = "{"+ re.sub('(|^)(?P<id>\w+)=(?P<val>\d+)', ' "\g<id>":\g<val>,', string) +"}" 
dict = eval(string2) 
print type(string), type(string2), type(dict) 
print string, string2, dict 

这里的正则表达式是相当原始,并荣获” t捕获所有可能的Python标识符,但为了简单起见,我想保持简单。 当然,如果您可以控制输入字符串的生成方式,只需根据python语法生成并将其评估即可。 但是,当然你应该执行额外的理智检查,以确保没有代码注入那里!

+2

你想保持这个简单?不要吝啬或挑选任何人,但这在哪里很简单? – Nope 2009-08-08 22:22:24

3

单线程没有列表理解的情况如何?

foo="a=0 b=1 c=3" 
ans=eval('dict(%s)'%foo.replace(' ',','))) 
print ans 
{'a': 0, 'c': 3, 'b': 1} 
+0

我知道eval如何工作,但我很难理解这个 – Ajay 2015-05-01 10:28:28

+1

foo.replace()将“a = 0 b = 1 c = 3”变成“a = 0,b = 1,c = 3”。字符串格式创建一个新的字符串“dict(a = 0,b = 1,c = 3)”。评估该字符串产生所需的字典。 – 2015-05-05 01:44:23

+0

我花了一段时间才明白.. – Ajay 2015-05-05 05:53:13

3

尝试了下:

dict([x.split('=') for x in s.split()]) 
+1

OP想要将列表中的第二个元素转换为整数。 – hughdbrown 2009-08-08 15:11:29

2

我有时喜欢这种方法,尤其是在制作键和值的逻辑比较复杂:

s = "a=0 b=1 c=3" 

def get_key_val(x): 
    a,b = x.split('=') 
    return a,int(b) 

ans = dict(map(get_key_val,s.split())) 
0

我这样做:

def kv(e): return (e[0], int(e[1])) 
d = dict([kv(e.split("=")) for e in string.split(" ")]) 
2

现在你s HOULD可能使用字典理解,在2.7介绍:

mydict = {key: int(value) for key, value in (a.split('=') for a in mystring.split())} 

的字典解析速度更快,更亮泽(和,在我看来,更具可读性)。

from timeit import timeit 

setup = """mystring = "a=0 b=1 c=3\"""" 
code1 = """mydict = dict((n,int(v)) for n,v in (a.split('=') for a in mystring.split()))""" # S.Lott's code 
code2 = """mydict = {key: int(value) for key, value in (a.split('=') for a in mystring.split())}""" 

print timeit(code1, setup=setup, number=10000) # 0.115524053574 
print timeit(code2, setup=setup, number=10000) # 0.105328798294