Joh*_*ard 199
这段代码应该有效:
>>> iter = (i for i in range(50))
>>> sum(1 for _ in iter)
50
Run Code Online (Sandbox Code Playgroud)
虽然它会遍历每个项目并对它们进行计数,但这是最快的方法.
它也适用于迭代器没有项目时:
>>> sum(1 for _ in range(0))
0
Run Code Online (Sandbox Code Playgroud)
Tom*_*cki 92
不,这是不可能的.
例:
import random
def gen(n):
for i in xrange(n):
if random.randint(0, 1) == 0:
yield i
iterator = gen(10)
Run Code Online (Sandbox Code Playgroud)
长度iterator
是未知的,直到你迭代它.
Dae*_*yth 62
不,任何方法都需要您解决每个结果.你可以做
iter_length = len(list(iterable))
Run Code Online (Sandbox Code Playgroud)
但是在无限迭代器上运行它当然永远不会返回.它也将使用迭代器,如果你想使用它,它将需要重置.
告诉我们你想要解决的真正问题可能会帮助我们找到更好的方法来实现你的实际目标.
编辑:使用list()
将立即将整个可迭代内容读入内存,这可能是不合需要的.另一种方法是做
sum(1 for _ in iterable)
Run Code Online (Sandbox Code Playgroud)
作为另一个人张贴.这样可以避免将其保留在内存中.
zuo*_*zuo 29
你不能(除了特定迭代器的类型实现了一些使它成为可能的特定方法).
通常,您只能通过使用迭代器来计算迭代器项.可能是最有效的方法之一:
import itertools
from collections import deque
def count_iter_items(iterable):
"""
Consume an iterable not reading it into memory; return the number of items.
"""
counter = itertools.count()
deque(itertools.izip(iterable, counter), maxlen=0) # (consume at C speed)
return next(counter)
Run Code Online (Sandbox Code Playgroud)
(对于Python 3.x的替换itertools.izip
用zip
).
bad*_*adp 17
均田.您可以检查该__length_hint__
方法,但要注意(至少在Python 3.4中,正如gsnedders帮助指出的那样)它是一个未记录的实现细节(在线程中的消息之后),这可能很好地消失或召唤鼻子恶魔.
否则,没有.迭代器只是一个只暴露next()
方法的对象.您可以根据需要多次调用它们,它们可能会或可能不会最终提升StopIteration
.幸运的是,这种行为大部分时间对编码人员来说是透明的.:)
Erw*_*yer 11
我喜欢它的基数包,它非常轻量级,并尝试使用可用的最快实现,具体取决于iterable.
用法:
>>> 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
Run Code Online (Sandbox Code Playgroud)
实际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
Run Code Online (Sandbox Code Playgroud)
迭代器只是一个对象,它有一个指向下一个要被某种缓冲区或流读取的对象的指针,它就像一个LinkedList,在你迭代它们之前你不知道你有多少东西.迭代器意味着效率很高,因为他们只是通过引用而不是使用索引来告诉你接下来是什么(但是你看到你失去了查看接下来有多少条目的能力).
因此,对于那些想了解该讨论摘要的人。使用以下方法计算长度为5000万的生成器表达式的最终最高分:
len(list(gen))
, len([_ for _ in gen])
, sum(1 for _ in gen),
ilen(gen)
(来自more_itertool),reduce(lambda c, i: c + 1, gen, 0)
, 按执行性能(包括内存消耗)排序,会让您感到惊讶:
```
gen = (i for i in data*1000); t0 = monotonic(); len(list(gen))
Run Code Online (Sandbox Code Playgroud)
(“列表,秒”,1.9684218849870376)
gen = (i for i in data*1000); t0 = monotonic(); len([i for i in gen])
Run Code Online (Sandbox Code Playgroud)
('list_compr,sec',2.5885991149989422)
gen = (i for i in data*1000); t0 = monotonic(); sum(1 for i in gen); t1 = monotonic()
Run Code Online (Sandbox Code Playgroud)
('sum,sec',3.441088170016883)
d = deque(enumerate(iterable, 1), maxlen=1)
test_ilen.py:10: 0.875 KiB
gen = (i for i in data*1000); t0 = monotonic(); ilen(gen)
Run Code Online (Sandbox Code Playgroud)
('ilen,sec',9.812256851990242)
gen = (i for i in data*1000); t0 = monotonic(); reduce(lambda counter, i: counter + 1, gen, 0)
Run Code Online (Sandbox Code Playgroud)
('reduce,sec',13.436614598002052)```
因此,len(list(gen))
是最频繁且消耗较少的内存
小智 8
关于你原来的问题,答案仍然是通常无法知道Python中迭代器的长度.
鉴于您的问题是由pysam库的应用推动的,我可以给出一个更具体的答案:我是PySAM的贡献者,并且明确的答案是SAM/BAM文件不提供对齐读取的精确计数.这个信息也不容易从BAM索引文件中获得.最好的方法是在读取多个对齐之后使用文件指针的位置估计对齐的近似数量,并根据文件的总大小进行外推.这足以实现进度条,但不是在恒定时间内计算对齐的方法.
快速基准:
import collections
import itertools
def count_iter_items(iterable):
counter = itertools.count()
collections.deque(itertools.izip(iterable, counter), maxlen=0)
return next(counter)
def count_lencheck(iterable):
if hasattr(iterable, '__len__'):
return len(iterable)
d = collections.deque(enumerate(iterable, 1), maxlen=1)
return d[0][0] if d else 0
def count_sum(iterable):
return sum(1 for _ in iterable)
iter = lambda y: (x for x in xrange(y))
%timeit count_iter_items(iter(1000))
%timeit count_lencheck(iter(1000))
%timeit count_sum(iter(1000))
Run Code Online (Sandbox Code Playgroud)
结果:
10000 loops, best of 3: 37.2 µs per loop
10000 loops, best of 3: 47.6 µs per loop
10000 loops, best of 3: 61 µs per loop
Run Code Online (Sandbox Code Playgroud)
即简单的count_iter_items是要走的路。
针对python3进行调整:
61.9 µs ± 275 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
74.4 µs ± 190 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
82.6 µs ± 164 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
101660 次 |
最近记录: |