2011-11-28 38 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