获取满足条件的列表百分比

1 投票
6 回答
1782 浏览
提问于 2025-04-17 22:28

这其实是个很简单的事情,可以用循环和其他一些不太优雅的方式来实现。不过,问题是有没有一种方法(最好是一行代码就能搞定),可以遍历一个列表,计算出符合某个条件的元素所占的百分比?比如说,

def predicate(x):
    #Returns if x is even
    return x % 2 == 0

#Performed on [1,2,3,4]
50

#Performed on [5,3,7,2]
25

有没有简单的方法可以做到这一点呢?

6 个回答

0

这是从需要一种快速的方法来在一次遍历中计数和求和可迭代对象中得到的一个结果。

这个答案可以处理任何可迭代的对象,包括生成器表达式。因为通常你不能直接获取生成器的长度,所以这个方法可能会很有用。

def predicate(x):
    #Returns if x is even
    return x % 2 == 0


def percentage(iterable, conditional):
    import itertools 
    from collections import deque 
    it = (1.0 if conditional(i) else 0.0 for i in iterable)
    res = deque(enumerate(itertools.accumulate(it), 1), maxlen=1)
    if len(res) == 0:
        return 0.0
    return 100.0 * res[0][1]/res[0][0]

L1 = [1,2,3,4] 
percentage(L1, predicate)
# 50.0
L2 = [5,3,7,2]
percentage(L2, predicate)
0

这里有一个非常快速的方法,它在Python 2和3中都能使用,能够处理空列表,而且只用一行代码就能完成:

def predicate(x):
    return x % 2 == 0  # x even?

for lst in [1,2,3,4], [5,3,7,2], []:
    print(0.0 if not lst else sum(map(predicate, lst), 0.0) / len(lst) * 100)

输出结果:

50.0
25.0
0.0
1

还有另一种方法可以利用 True 等于 1False 等于 0 的特性:

sum(map(property, your_list), 0.0) / len(your_list) * 100
3

先计算与 sum() 匹配的数量,然后用这个数量除以总长度,再乘以 100。

def percentage(L, predicate):
    return (sum(1.0 for v in L if predicate(v)) / len(L)) * 100

这样做不会额外创建列表对象,所以这个算法的内存使用是固定的。

示例:

>>> def percentage(L, predicate):
...     return (sum(1.0 for v in L if predicate(v)) / len(L)) * 100
... 
>>> def property(x):
...     #Returns if x is even
...     return x % 2 == 0
... 
>>> percentage([1,2,3,4], property)
50.0
>>> percentage([5,3,7,2], property)
25.0
1

这样怎么样?

100 * ( len([x for x in l if property(x)]) / len(l) )

撰写回答