检查迭代的长度是否至少n
的Pythonic方法是什么?
这是我的方法:
import itertools
def is_iterable_longer_than(iterable, n):
return n <= len(itertools.islice(iterable, n))
有什么更好的吗?
修改
我愿意使用迭代,即使它只能被评估一次。
正如所指出的,上面有一个错误。它应该是:
return n <= len(list(itertools.islice(iterable, n)))
答案 0 :(得分:3)
没有一般方法。你甚至不工作:
>>> def is_iterable_longer_than(iterable, n):
... return n <= len(itertools.islice(iterable, n))
...
>>> is_iterable_longer_than([], 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in is_iterable_longer_than
TypeError: object of type 'itertools.islice' has no len()
判断迭代中是否至少包含n
个对象的唯一方法是迭代它,直到得到n
个对象或用完为止。不幸的是,一些迭代只能迭代一次。如果您不关心使用iterable的内容,可以这样做:
def is_iterable_longer_than(iterable, n):
return n == sum(1 for _ in itertools.islice(iterable, n))
如果需要使用iterable的内容,可以创建另一个看起来像原始的迭代:
def is_iterable_longer_than(iterable, n):
iter1, iter2 = itertools.tee(iterable)
return sum(1 for _ in itertools.islice(iter1, n)) == n, iter2
虽然我们正在努力,但我们也可以尝试len
,以防它起作用:
def is_iterable_longer_than(iterable, n):
iter1, iter2 = itertools.tee(iterable)
try:
return len(iterable) >= n, iter2
except TypeError:
return sum(1 for _ in itertools.islice(iter1, n)) == n, iter2
答案 1 :(得分:2)
这取决于你是否愿意评估发电机。
如果你是,那很简单:
def gen_length_was_at_least_n(gen, n):
return n == sum(1 for _ in itertools.islice(gen, n))
如果你不是,那么你就会陷入困境,除非你愿意对它进行评估,但要保持通过tee
缓存的值:
gen, extra = itertools.tee(gen)
if gen_length_was_at_least_n(extra):
# ... do something with gen
请注意,此 部分评估原始迭代器;它只保留值,并通过tee
返回的新生成器为它们提供服务。这意味着如果评估发电机有副作用,那么在进行长度检查时会触发它们。