Python双重循环

19

如何用Pythonic的方式同时迭代两个列表?

假设我想逐行比较两个文件(将一个文件的第i行与另一个文件的第i行进行比较),我会像这样做:

file1 = csv.reader(open(filename1),...)
file2 = csv.reader(open(filename2),...)

for line1 in file1 and line2 in file2: #pseudo-code!
    if line1 != line2:
        print "files are not identical"
        break

有一个Pythonic的方法可以实现这个吗?


编辑: 我没有使用文件处理程序,而是使用了CSV读取器 (csv.reader(open(file),...)), zip() 似乎无法与其一起使用...


最终编辑: 像@Alex M.建议的那样,zip() 在第一次迭代时会将文件加载到内存中,所以在大文件上使用会有问题。在Python 2中,使用 itertools 可以解决这个问题。


可能是如何在Python中并行迭代两个列表?的重复问题。 - Ciro Santilli OurBigBook.com
3个回答

16

在Python 2中,你应该导入itertools并使用其中的izip函数:

with open(file1) as f1:
  with open(file2) as f2:
    for line1, line2 in itertools.izip(f1, f2):
      if line1 != line2:
        print 'files are different'
        break

使用内置的zip函数,循环开始时,两个文件将一次性完全读入内存,这可能不是你想要的。在Python 3中,内置zip函数类似于Python 2中的itertools.izip函数,可以逐步读取。


这个完成了任务!确实问题是文件太大,zip()将它们全部加载到内存中... - Yuval Adam
啊,也许这就是为什么我看不出任何区别的原因。我正在使用Python 3.1。 - kennytm
@KennyTM,没错,Python 3中许多以前依赖于Python 2中全内存列表的东西已经变成了增量和迭代式的。因此,始终澄清问题和答案是否涉及Python 2或Python 3非常重要--在Python 2中,(更好的;-)增量和迭代方法是“选择加入”的(需要显式获取),而在 Python 3中,它是内在的(在相对罕见的情况下,您实际上确实需要一次性全部存储内存的列表,需要显式调用list)。 - Alex Martelli
只是一个小提示:如果您愿意,您可以在同一个 with 语句中打开两个文件:with open(file1) as f1, open(file2) as f2: - Daan Timmer

11

我赞成使用 zip。Python的手册建议“要同时循环两个或多个序列,可以使用zip()函数将其配对”。

例如:

list_one = ['nachos', 'sandwich', 'name']
list_two = ['nachos', 'sandwich', 'the game']
for one, two in zip(list_one, list_two):
   if one != two:
      print "Difference found"

4

在Python ≥3中的锁步执行:

for line1, line2 in zip(file1, file2):
   # etc.

作为“二维数组”:
for line1 in file1:
   for line2 in file2:
     # etc.
   # you may need to rewind file2 to the beginning.

谢谢,我正在寻找锁步方法。你有什么想法为什么这种方法对于csv.reader()无效? - Yuval Adam
也许你应该澄清一下对于“2D数组”,可能需要重新初始化内部迭代器... - fortran
1
@Yuval,请编辑您的答案,以显示您如何尝试使用zip与一个csv.reader -- 这个评论完全是神秘的。 - Alex Martelli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接