【问题标题】:Pythonic way for generator length at least n生成器长度至少为 n 的 Pythonic 方式
【发布时间】:2014-01-04 01:57:36
【问题描述】:

检查可迭代对象的长度是否至少为 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)))

【问题讨论】:

  • 如果不评估来自生成器的至少 n 值,则无法这样做。
  • @JoelCornett,我知道我需要评估生成器。我想知道最好的方法。显然,我不想评估超出必要的内容,而且没有中间数据结构会很棒。我希望它非常清晰和简洁。

标签: python iterable


【解决方案1】:

没有通用的方法。你的甚至都行不通:

>>> 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 对象或用完为止。不幸的是,一些可迭代对象只能迭代一次。如果你不关心使用可迭代的内容,你可以这样做:

def is_iterable_longer_than(iterable, n):
    return n == sum(1 for _ in itertools.islice(iterable, n))

如果你需要使用iterable的内容,你可以创建另一个看起来像原来的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

【讨论】:

    【解决方案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 返回的新生成器为它们提供服务。这意味着如果评估生成器有副作用,它们将在您进行长度检查时被触发。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-30
      • 1970-01-01
      • 2014-11-04
      相关资源
      最近更新 更多