一般来说,有没有一种有效的方法可以知道Python中的迭代器中有多少个元素,而不用遍历每个元素并计数?
当前回答
假设,您希望在不遍历的情况下计算项的数量,这样迭代器就不会耗尽,稍后可以再次使用它。这是可能的复制或深度复制
import copy
def get_iter_len(iterator):
return sum(1 for _ in copy.copy(iterator))
###############################################
iterator = range(0, 10)
print(get_iter_len(iterator))
if len(tuple(iterator)) > 1:
print("Finding the length did not exhaust the iterator!")
else:
print("oh no! it's all gone")
输出是“查找长度没有耗尽迭代器!”
可选的(并且不明智的),你可以像下面这样为内置的len函数添加阴影:
import copy
def len(obj, *, len=len):
try:
if hasattr(obj, "__len__"):
r = len(obj)
elif hasattr(obj, "__next__"):
r = sum(1 for _ in copy.copy(obj))
else:
r = len(obj)
finally:
pass
return r
其他回答
虽然一般情况下不可能按照要求去做,但在迭代了多少项之后,对它们进行迭代的次数进行计数通常仍然是有用的。为此,您可以使用jaraco.itertools.Counter或类似的方法。下面是一个使用python3和rwt加载包的例子。
$ rwt -q jaraco.itertools -- -q
>>> import jaraco.itertools
>>> items = jaraco.itertools.Counter(range(100))
>>> _ = list(counted)
>>> items.count
100
>>> import random
>>> def gen(n):
... for i in range(n):
... if random.randint(0, 1) == 0:
... yield i
...
>>> items = jaraco.itertools.Counter(gen(100))
>>> _ = list(counted)
>>> items.count
48
我喜欢这个基数包,它是非常轻量级的,并尝试使用最快的实现,这取决于可迭代对象。
用法:
>>> import cardinality
>>> cardinality.count([1, 2, 3])
3
>>> cardinality.count(i for i in range(500))
500
>>> def gen():
... yield 'hello'
... yield 'world'
>>> cardinality.count(gen())
2
count()的实际实现如下:
def count(iterable):
if hasattr(iterable, '__len__'):
return len(iterable)
d = collections.deque(enumerate(iterable, 1), maxlen=1)
return d[0][0] if d else 0
这违背了迭代器的定义,迭代器是一个指向对象的指针,加上如何到达下一个对象的信息。
迭代器不知道在终止之前它还能迭代多少次。这个可以是无穷,所以无穷可能是你的答案。
关于你最初的问题,答案仍然是,在Python中通常没有办法知道迭代器的长度。
Given that you question is motivated by an application of the pysam library, I can give a more specific answer: I'm a contributer to PySAM and the definitive answer is that SAM/BAM files do not provide an exact count of aligned reads. Nor is this information easily available from a BAM index file. The best one can do is to estimate the approximate number of alignments by using the location of the file pointer after reading a number of alignments and extrapolating based on the total size of the file. This is enough to implement a progress bar, but not a method of counting alignments in constant time.
通常的做法是将这类信息放在文件头中,并让pysam允许您访问这些信息。我不知道格式,但是你检查过API了吗?
正如其他人所说,你不能从迭代器中知道长度。