【问题标题】:How to find the length of a "filter" object in python如何在python中找到“过滤器”对象的长度
【发布时间】:2013-10-11 12:12:47
【问题描述】:
>>> n = [1,2,3,4]

>>> filter(lambda x:x>3,n)
<filter object at 0x0000000002FDBBA8>

>>> len(filter(lambda x:x>3,n))
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    len(filter(lambda x:x>3,n))
TypeError: object of type 'filter' has no len()

我无法得到我得到的列表的长度。所以我试着把它保存到一个变量中,像这样......

>>> l = filter(lambda x:x>3,n)
>>> len(l)
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    len(l)
TypeError: object of type 'filter' has no len()

除了使用循环之外,有什么办法可以得到这个的长度吗?

【问题讨论】:

  • 没有办法知道生成器在生成对象之前会生成多少对象。如果您关心优化,您可以使用先验信息来加快速度 - 即,如果您知道您的列表已排序,您可以丢弃 index(3) 下方的项目。

标签: python-3.x filter variable-length


【解决方案1】:

您必须以某种方式遍历过滤器对象。一种方法是将其转换为列表:

l = list(filter(lambda x: x > 3, n))

len(l)  # <--

但这可能会破坏首先使用filter() 的意义,因为您可以通过列表理解更轻松地做到这一点:

l = [x for x in n if x > 3]

同样,len(l) 将返回长度。

【讨论】:

  • 这是最简单的方法,但不是真正正确的方法。我更喜欢 Al Hoo 和 tso 的回答。可惜python内部不支持reduce方式!
  • 如果n 非常大,此解决方案会占用大量额外内存。
  • 注意你不能做next(l),因为过滤器对象已经以某种方式“使用”了。
【解决方案2】:

这是一个老问题,但我认为这个问题需要使用 ma​​p-reduce 思想来回答。 所以在这里:

from functools import reduce

def ilen(iterable):
    return reduce(lambda sum, element: sum + 1, iterable, 0)

ilen(filter(lambda x: x > 3, n))

如果n 不适合计算机内存,这尤其有用。

【讨论】:

  • 这比使用列表迭代的 len 快吗?
  • 不是用python,但是如果你想优化一些需要过滤对象长度的算法,建立一个列表来计算长度并不是最优的方式。
  • 请注意,reduce 在 Python 3.0 及更高版本中被故意从标准库中删除。关于为什么做出决定的更多细节可以在 Guido van Rossum 的这个帖子中找到:artima.com/weblogs/viewpost.jsp?thread=98196
【解决方案3】:

将过滤器转换为列表会占用额外的内存,这对于大量数据可能是不可接受的。您可以在不将其转换为列表的情况下找到过滤器对象的长度:

sum(1 for _ in filter(lambda x: x &gt; 3, n))

【讨论】:

    【解决方案4】:

    python 3 的 docs 表示它返回一个迭代器

    "从可迭代的那些元素构造一个迭代器 函数返回 true。”

    在 python 2 中它返回了一个列表:见here。 您将需要迭代过滤器对象以找到它的长度。

    【讨论】:

      【解决方案5】:

      一般来说,filterreduce 不是 pythonic。

      @arshajii 提到了这个解决方案:

      len([x for x in n if x > 3])
      

      这很简单,但并没有描述您真正想要做什么,它会创建一个可能会使用一些额外内存的列表。 更好的解决方案是使用 sum 和生成器:

      sum(1 for x in n if x > 3)
      

      (在此处查看有关生成器的更多信息:https://www.python.org/dev/peps/pep-0289/#rationale

      然而,sum 与生成器在大多数情况下实际上速度较慢,因为实现(在 CPython 3.6.4 中测试):

      In [1]: %timeit len([1 for x in range(10000000)])
      356 ms ± 17.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
      
      In [2]: %timeit sum(1 for x in range(10000000))
      676 ms ± 7.05 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-28
        • 2015-11-25
        • 2017-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多