python - 如何检测两个Python迭代器产生相同的项目?

标签 python python-2.7 iterator compare

是否有一种简洁且节省内存的方法来确定两个迭代器 lines1lines2 是否产生相同的项目?

例如,这些迭代器可以是从文件对象检索的行:

with io.open(`some.txt`, 'r', encoding='...') as lines1:
  with io.open(`other.txt`, 'r', encoding='...') as lines2:
    lines_are_equal = ...

直觉上人们可以预料到

lines_are_equal = lines1 == lines2  # DOES NOT WORK

将给出所需的结果。然而,这将始终是False,因为它只比较迭代器的地址而不是产生的项目。

如果内存不是问题,可以将迭代器转换为列表并比较它们:

lines_are_equal = list(lines1) == list(lines2)  # works but uses a lot of memory

我已经检查了 itertools,希望找到类似的东西

lines_are_equal = itertools.equal(lines1, lines2)  # DOES NOT WORK

但是好像没有这样的功能。

到目前为止,我能想到的最好的方法是使用 itertools.zip_longest() 循环两个迭代器(Python 2:izip_longest()):

lines_are_equal = True
for line1, line2 in itertools.zip_longest(lines1, lines2):
  if line1 != line2:
    lines_are_equal = False
    break

这确实给出了所需的结果,并且内存效率高,但感觉笨拙且不符合Python风格。

有更好的方法吗?

解决方案:应用评论中的集体智慧并回答这是一个单行辅助函数,即使两个迭代器相同或可以有尾随 None值:

def iter_equal(items1, items2):
  '''`True` if iterators `items1` and `items2` contain equal items.'''
  return (items1 is items2) or \
          all(a == b for a, b in itertools.zip_longest(items1, items2, fillvalue=object()))

您仍然必须确保迭代器不会相互产生副作用。

最佳答案

使用 all 怎么样?使用生成器表达式:

lines_are_equal = all(a == b for a, b in itertools.zip_longest(lines1, lines2))

UPDATE 如果 iterable 可以生成尾随 None,则最好按照 user2357112 的评论指定 fillvalue=object() 。 (默认情况下,None 用于填充值)

lines_are_equal = all(a == b for a, b in
                      itertools.zip_longest(lines1, lines2, fillvalue=object()))

如果您的目的是比较两个文件,而不是任何可迭代文件,则可以使用 filecmp.cmp相反:

files_are_equal = filecmp.cmp(filename1, filename2)

关于python - 如何检测两个Python迭代器产生相同的项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25216504/

相关文章:

python - x tan(x) - b 的零点

python - 按列对分组数据框进行采样

python - 如何打印不带括号、逗号和引号的整数列表?

rust - 在 Rust 中格式化字节切片

python - python模块存储在哪里?

python - 运行图时出现异常: Unable to get element from the feed as bytes

python - 用于测试字符串的可能值的有限调色板的正则表达式?

python - Tkinter 类中的 title() 方法和 wm_title() 方法有什么区别?

C++ std::reduce 与数组

Java:在修改集合内容时迭代集合