2011-12-21 598 views
3

我想比較來自兩個不同文件的列的數據。我試圖使用for,現在是list comprehensionPython中嵌套循環(列表理解);外循環不循環

問題是外循環沒有被迭代,但內循環是。我已經單獨檢查過了,迭代很好;但一旦我嵌套,我得到這個問題。我有沒有想到這件事?

import csv 

newInv = csv.reader(open("new.csv", "r")) 
origInv = csv.reader(open("old.csv", "r")) 

print [ oldrow[5] + " " + newrow[3] for oldrow in origInv for newrow in newInv ] 
+0

你應該更具體和準確地描述你想要達到的目標。你在談論比較,我沒有看到你的代碼中有任何比較。它是否適用於'for'循環?如果沒有,爲什麼要嘗試「列表推導」(這是您的級別的優化)? – Stan 2011-12-27 20:34:33

回答

3

外部迭代。但是,內循環僅執行第一個迭代的外循環 - 然後到達newInv的結尾。

瞭解newInv不是您可以迭代多次的集合。它是一個迭代器,只能使用一次。試試這個(未經測試):

newInv = list(csv.reader(open("new.csv", "r"))) 
origInv = list(csv.reader(open("old.csv", "r"))) 

它會將數據複製到內存中並允許您迭代多次。

+1

我最喜歡你的解決方案;更容易與之合作。 – user1110559 2011-12-22 13:15:44

9

注意,在解決方案中的for循環嵌套,所以這就是爲什麼一個循環似乎重複,而另一人似乎沒有。

你需要使用在同一時間獲得兩個迭代器的一個要素是itertools.izip

[ oldrow[5] + " " + newrow[3] 
for oldrow, newrow in itertools.izip(origInv, newInv)] 
1

這可能是一個簡單的問題,您的括號。

print [[(expression with i and j) for i in foo] for j in bar] 
+0

您的列表括號不匹配。你需要另一個'['。 – Edwin 2011-12-21 20:27:39

+0

謝謝!糾正。 – 2011-12-21 20:29:14

3

這裏有兩件事情。

1)您的列表理解有兩個迭代。從概念上講,您需要重新爲每個oldrow重複newInv

2)你看不到(oldRow,NEWROW)的每個組合的原因,就像你所期望給出的第一點,就是一個csv.reader,因而只能使用一次遍歷。每個隨後的「迭代」newInv都沒有找到新的項目,因爲它們都是第一次「用完」。

爲了得到(舊行,新行),形式從每個csv.reader第一list S的每個組合(可以直接通過他們的list構造。

要獲得的成對組合的一個序列(舊的行,新行),zip兩個csv.reader小號在一起。

1

從文檔

itertools.product(*iterables[, repeat]) 
Cartesian product of input iterables. 

等效嵌套for循環在發電機的表達。佛例如,產品(A,B)對於B中的y返回與((x,y)中的x相同的A)。

嵌套循環像一個里程錶一樣循環,最右邊的元素在每次迭代中前進。這種模式創建了一個詞典排序,因此如果輸入的可迭代序列被排序,則產品元組將按排序順序排列。

要計算迭代本身的乘積,請使用可選的repeat關鍵字參數指定重複次數。例如,產品(A,重複= 4)意味着與產品(A,A,A,A)相同。

此功能相當於下面的代碼,但實際執行並不在內存中建立中間結果:在2.6版本

def product(*args, **kwds): 
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy 
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 
    pools = map(tuple, args) * kwds.get('repeat', 1) 
    result = [[]] 
    for pool in pools: 
     result = [x+[y] for x in result for y in pool] 
    for prod in result: 
     yield tuple(prod) 

新建。