python:在特定条件下从列表(序列)中获取项目数

Posted

技术标签:

【中文标题】python:在特定条件下从列表(序列)中获取项目数【英文标题】:Get number of items from list (or other iterable) with certain condition 【发布时间】:2013-02-28 18:49:42 【问题描述】:

假设我有一个包含大量项目的列表。

l = [ 1, 4, 6, 30, 2, ... ]

我想从该列表中获取项目数,其中项目应满足特定条件。我的第一个想法是:

count = len([i for i in l if my_condition(l)])

但如果 my_condition() 过滤列表也有大量项目,我认为 为过滤结果创建新列表只是浪费内存。为了效率,恕我直言,上面的调用不能比:

count = 0
for i in l:
    if my_condition(l):
        count += 1

有没有什么函数式的方法可以在不生成临时列表的情况下获得满足特定条件的项目数?

提前致谢。

【问题讨论】:

生成器和列表之间的选择是执行时间和内存消耗之间的选择。如果您分析代码,您会惊讶于结果与直觉相反的频率。过早的优化是万恶之源。 【参考方案1】:

您可以使用generator expression:

>>> l = [1, 3, 7, 2, 6, 8, 10]
>>> sum(1 for i in l if i % 4 == 3)
2

甚至

>>> sum(i % 4 == 3 for i in l)
2

它使用了int(True) == 1这一事实。

或者,您可以使用 itertools.imap (python 2) 或简单地使用 map (python 3):

>>> def my_condition(x):
...     return x % 4 == 3
... 
>>> sum(map(my_condition, l))
2

【讨论】:

@mgilson:我认为它从来没有进行过这种计算——start 默认为 0,所以第一个加法是 True + 0,不是吗? 是的。也许我应该更清楚...... int(True) 是什么并不重要。 int("1") == 1 也可以,但这并不意味着你可以做到 "1" + 0。重要的是python如何评估integer + Trueinteger + False @mgilson:嗯,好吧,你说服了我。 重点是 boolint 的子类,因此您可以轻松添加布尔值和整数(True 的值为 1,False 的值为0). 嗯,这就是我提到int(True) == 1 的意思,但你的观点int("1") == 1 证明,以这种方式缩写它可能暗示不正确的事情。【参考方案2】:

您需要generator comprehension,而不是此处的列表。

例如,

l = [1, 4, 6, 7, 30, 2]

def my_condition(x):
    return x > 5 and x < 20

print sum(1 for x in l if my_condition(x))
# -> 2
print sum(1 for x in range(1000000) if my_condition(x))
# -> 14

或者使用itertools.imap(虽然我认为显式列表和生成器表达式看起来更像Pythonic)。

请注意,尽管在 sum 示例中并不明显,但您可以很好地编写生成器推导。例如,

inputs = xrange(1000000)      # In Python 3 and above, use range instead of xrange
odds = (x for x in inputs if x % 2)  # Pick odd numbers
sq_inc = (x**2 + 1 for x in odds)    # Square and add one
print sum(x/2 for x in sq_inc)       # Actually evaluate each one
# -> 83333333333500000

这项技术很酷的一点是,您可以在代码中指定概念上单独的步骤,而无需强制评估和存储在内存中,直到评估最终结果。

【讨论】:

【参考方案3】:

如果您更喜欢函数式编程,也可以使用 reduce 来完成此操作

reduce(lambda count, i: count + my_condition(i), l, 0)

这样你只做 1 遍,不会生成中间列表。

【讨论】:

【参考方案4】:

你可以这样做:

l = [1,2,3,4,5,..]
count = sum(1 for i in l if my_condition(i))

只为满足条件的每个元素加 1。

【讨论】:

【参考方案5】:
from itertools import imap
sum(imap(my_condition, l))

【讨论】:

imap 不适用于当前的 Python。

以上是关于python:在特定条件下从列表(序列)中获取项目数的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有 \n 的情况下从 txt 中获取特定行(Python)

在特定条件下从数据框中提取行

从模型列表中获取模型[关闭]

在特定条件下从 firebase 数据库中检索数据

SQL - 在特定条件下从多行中仅选择一个值

Python列表之元组