我希望能将可迭代对象中的所有元素进行组合比较。下面这个可以复现的例子只是模拟了一个普通列表的功能,但展示了我的问题。在这个由["A","B","C","D"]组成的列表中,我希望获得以下16行输出,即每个元素与其他元素的组合。一个包含100个元素的列表应该生成10,000行。
A A True
A B False
A C False
... 10 more lines ...
D B False
D C False
D D True
以下代码看起来应该能够完成任务。
class C():
def __init__(self):
self.stuff = ["A","B","C","D"]
def __iter__(self):
self.idx = 0
return self
def __next__(self):
self.idx += 1
if self.idx > len(self.stuff):
raise StopIteration
else:
return self.stuff[self.idx - 1]
thing = C()
for x in thing:
for y in thing:
print(x, y, x==y)
但是在完成y循环后,x循环似乎也已经完成了,尽管它只使用了可迭代对象中的第一个项目。
A A True
A B False
A C False
A D False
经过长时间的搜索,我最终尝试了以下代码,希望itertools.tee能够让我在相同数据上获得两个独立的迭代器:
import itertools
thing = C()
thing_one, thing_two = itertools.tee(thing)
for x in thing_one:
for y in thing_two:
print(x, y, x==y)
但我得到了与之前相同的输出结果。
该对象表示的是一个目录和文件结构的模型,其中包含不同数量和深度的文件和子目录。它具有嵌套链接到数千个成员,并且像此示例一样正确地迭代它们一次。但它还会在需要进行比较时在其许多内部对象中进行昂贵的处理,如果必须在迭代之前完全复制它,将导致工作量加倍。如果可能的话,我真的想使用多个迭代器,指向一个带有所有数据的单个对象。
编辑回答:所有答案都指出问题代码的关键缺陷是无法独立处理多个调用者的单个内部self.idx变量。接受的答案是适用于我的真实类(在这个可重现的示例中过于简化),另一个答案为像这里呈现的简单数据结构提供了一种简单而优雅的解决方案。
__len__
方法? - Eric Ed Lohmarrange
上使用嵌套的for
循环,并将结果数字用作索引?类似这样:for x in range(len(obj)): for y in range(len(obj)): print(obj[x] == obj[y])
- Eric Ed Lohmar