如何有效的Python列表理解中筛选计算值?(How do I efficiently filter

2019-07-01 21:46发布

Python的列表理解语法,可以很容易地理解一个过滤器内的值。 例如:

result = [x**2 for x in mylist if type(x) is int]

将返回MYLIST整数的平方的列表。 然而,如果测试涉及到一些(昂贵)的计算,并要对结果进行过滤? 一种选择是:

result = [expensive(x) for x in mylist if expensive(x)]

这将导致非“假”昂贵(x)的值的列表,但是昂贵的()为每个x叫了两声。 是否有一个理解语法,允许你做这个测试,而只有调用每一次X贵吗?

Answer 1:

如果计算已经很好地捆绑到功能,如何使用filtermap

result = filter (None, map (expensive, mylist))

您可以使用itertools.imap如果该列表是非常大的。



Answer 2:

想出了思想的一分钟后,我自己的答案。 它可以与嵌套的内涵进行:

result = [y for y in (expensive(x) for x in mylist) if y]

我想这作品,虽然我觉得嵌套的内涵是只能勉强可读



Answer 3:

最明显的(并且我认为最可读的)答案是不使用列表理解或发电机的表达,而是一个真正的发电机:

def gen_expensive(mylist):
    for item in mylist:
        result = expensive(item)
        if result:
            yield result

它需要更多的横向空间,但它更容易看到它做什么,一目了然,你最终不会重复自己。



Answer 4:

result = [x for x in map(expensive,mylist) if x]

地图()将返回在MYLIST每个对象的值的列表传递给昂贵()。 然后,你可以列出,理解这一点,放弃不必要的值。

这有点像一个嵌套的理解,但应该快了(因为Python解释器可以很方便地优化它)。



Answer 5:

这是发电机适合于处理到底是什么:

result = (expensive(x) for x in mylist)
result = (do_something(x) for x in result if some_condition(x))
...
result = [x for x in result if x]  # finally, a list
  1. 这使得它完全清楚是什么在管道的每个阶段发生。
  2. 明确了隐
  3. 使用发电机随处可见,直到最后一步,所以没有大的中间列表

CF: “发电机诀窍系统程序员”由大卫·比兹利



Answer 6:

你总是可以memoize的的expensive()函数,以便调用它的第二次,仅仅是为了计算值查找x

这里只是memoize的的许多实现的装饰之一 。



Answer 7:

你可以memoize的昂贵(X)(如果你经常打电话贵(X),你应该memoize的任何方式本页面给出了蟒蛇memoize的的实现:

http://code.activestate.com/recipes/52201/

这有昂贵(x)可以比N次被跑,因为任何重复的条目将利用备忘录上一次执行额外的好处。

请注意,这是假定贵(x)是一个真正的功能,并且不依赖于可能改变外部状态。 如果贵(X)不依赖于外部的状态,您可以在检测到状态的改变,或者你知道它不会列表理解过程中改变,那么你就可以修真前的备忘录复位。



Answer 8:

我将有一个偏好:

itertools.ifilter(bool, (expensive(x) for x in mylist))

这样做的优点是:

  • 避免无作为功能(将在Python 3被消除): http://bugs.python.org/issue2186
  • 只使用迭代器。


Answer 9:

还有就是普通的老使用的for循环追加到一个列表,太:

result = []
for x in mylist:
    expense = expensive(x)
    if expense:
        result.append(expense)


文章来源: How do I efficiently filter computed values within a Python list comprehension?