2011-11-28 67 views
2
>>> c = 'A/B,C/D,E/F' 
>>> [a for b in c.split(',') for (a,_) in b.split('/')] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in <listcomp> 
ValueError: need more than 1 value to unpack 

预期的结果是['A', 'C', 'E']这个嵌套列表理解有什么问题?

这是我所期待做到这一点,但显然又回到了前面的Python:

>>> [a for (a, _) in b.split('/') for b in c.split(',')] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'b' is not defined 

回答

5

你失败的原因是b.split('/')没有产生一个2元组。 双列表理解意味着你想把笛卡尔产品当作平面流而不是矩阵。那就是:

>>> [x+'/'+y for y in 'ab' for x in '012'] 
['0/a', '1/a', '2/a', '0/b', '1/b', '2/b'] 
    # desire output 0,1,2 
    # not output 0,1,2,0,1,2 

你是不是在找6个回答,您正在寻找3.你想要的是:

>>> [frac.split('/')[0] for frac in c.split(',')] 
['A', 'C', 'E'] 

即使你使用了嵌套列表理解,你会得到你笛卡尔乘积(3×2 = 6),并意识到你有重复的信息(你不需要X2):

>>> [[x+'/'+y for y in 'ab'] for x in '012'] 
[['0/a', '0/b'], ['1/a', '1/b'], ['2/a', '2/b']] 
    # desire output 0,1,2 
    # not [0,0],[1,1],[2,2] 

以下是做同样事情的等效方法。尽管我比较了这种比较中生成器和列表之间的主要区别。以列表形式

笛卡尔乘积:

((a,b,c) for a in A for b in B for c in C) 
      #SAME AS# 
((a,b,c) for (a,b,c) in itertools.product(A,B,C)) 
      #SAME AS# 
for a in A: 
    for b in B: 
     for c in C: 
      yield (a,b,c) 

在矩阵形式的笛卡尔乘积:

[[[(a,b,c) for a in A] for b in B] for c in C] 
      #SAME AS# 
def fC(c): 
    def fB(b,c): 
     def fA(a,b,c): 
      return (a,b,c) 
     yield [f(a,b,c) for a in A] 
    yield [fB(b,c) for b in B] 
[fC(c) for c in C] 
      #SAME AS# 
Cs = [] 
for c in C: 
    Bs = [] 
    for b in B: 
     As = [] 
     for a in A: 
      As += [a] 
     Bs += [As] 
    Cs += [Bs] 
return Cs 

重复的功能应用到列表

({'z':z} for x in ({'y':y} for y in ({'x':x} for x in 'abc'))) 
       #SAME AS# 
for x in 'abc': 
    x2 = {'x':x} 
    y2 = {'y':x2} 
    z2 = {'z':y2} 
    yield z2 
       #SAME AS# 
def f(x): 
    return {'z':{'y':{'x':x}}} 
return [f(x) for x in 'abc']  # or map(f,'abc') 
4
[x.split('/')[0] for x in [a for a in c.split(',')]] 

这得到所需的['一个', 'C','E']从c ='A/B,C/D,E/F'

+0

以供将来参考,您可以在内部生成器周围放置'(...)'以避免创建不必要的中间名单,而不是'[...]' – ninjagecko

+1

谢谢你将来会记录下...... :) – avasal