列表中大于某个数的值的数量

90
我有一组数字,我想要在满足某些条件的列表中获取数字出现的次数。我可以使用列表推导式(或在函数中使用列表推导式),但我想知道是否有更短的方法。
# list of numbers
j=[4,5,6,7,1,3,7,5]
#list comprehension of values of j > 5
x = [i for i in j if i>5]
#value of x
len(x)

#or function version
def length_of_list(list_of_numbers, number):
     x = [i for i in list_of_numbers if j > number]
     return len(x)
length_of_list(j, 5)

有更加简洁的版本吗?

9个回答

185

你可以像这样做:

>>> j = [4, 5, 6, 7, 1, 3, 7, 5]
>>> sum(i > 5 for i in j)
3

一开始这种方式可能看起来很奇怪,将 True 加到 True 上,但我认为这并不是不符合 Python 风格的;毕竟,bool 在自从 2.3 版本以来的所有版本中都是 int 的子类:(详情请见链接)

>>> issubclass(bool, int)
True

1
@jamylak,这比Greg Hewgill的更好在哪里?虽然它很有趣且正确,但对于其他人阅读代码来说,它似乎不太直观和显而易见。 - TJD
1
@TJD 没有说它更好,但我更喜欢它。 - jamylak
@senderle:(格雷格之前的删除答案。我添加了一个新的答案,可以解决问题。 :) - Greg Hewgill
7
如果有这个意图的话,“sum(1 for i in j if i > 5)”可能需要更加明确。sum(1 for ... if ...)也可以隐藏在count函数中。 - Niklas B.
@NiklasB.,啊,当然你是对的-甚至不需要条件表达式。 - senderle

24

你可以像这样创建一个更小的中间结果:

>>> j = [4, 5, 6, 7, 1, 3, 7, 5]
>>> len([1 for i in j if i > 5])
3

15
可以使用sum(1 for i in j if i > 5)避免将列表加载到内存中。该代码不改变原意,只是更加简明易懂。 - jamylak

16

如果你已经在使用numpy,那么你可以省略一些代码,但我认为这并不能比senderle的答案更快/更简洁。

import numpy as np
j = np.array(j)
sum(j > i)

4
如果您正在使用NumPy(如ludaavic的答案),对于大型数组,您可能希望使用NumPy的sum函数而不是Python内置的sum函数,以获得显著的加速效果 - 例如,在我的笔记本电脑上,对于1000万个元素的数组,可以加速超过1000倍。
>>> import numpy as np
>>> ten_million = 10 * 1000 * 1000
>>> x, y = (np.random.randn(ten_million) for _ in range(2))
>>> %timeit sum(x > y)  # time Python builtin sum function
1 loops, best of 3: 24.3 s per loop
>>> %timeit (x > y).sum()  # wow, that was really slow! time NumPy sum method
10 loops, best of 3: 18.7 ms per loop
>>> %timeit np.sum(x > y)  # time NumPy sum function
10 loops, best of 3: 18.8 ms per loop

(上述使用IPython的%timeit “魔术”进行计时)

4

一种(稍微)不同的方式:

reduce(lambda acc, x: acc + (1 if x > 5 else 0), j, 0)

这行代码使用Python中的reduce函数,对列表j中的元素进行迭代,并将结果累加到变量acc中。如果当前元素大于5,则添加1,否则添加0。最终返回的是累加后的值。

3
使用bisect模块进行计数的不同方法:
>>> from bisect import bisect
>>> j = [4, 5, 6, 7, 1, 3, 7, 5]
>>> j.sort()
>>> b = 5
>>> index = bisect(j,b) #Find that index value
>>> print len(j)-index
3

2
我会添加一个map和filter的版本,因为为什么不呢。
sum(map(lambda x:x>5, j))
sum(1 for _ in filter(lambda x:x>5, j))

1
你可以使用函数来实现这个功能,具体方法如下:

l = [34,56,78,2,3,5,6,8,45,6]  
print ("The list : " + str(l))   
def count_greater30(l):  
    count = 0  
    for i in l:  
        if i > 30:  
            count = count + 1.  
    return count
print("Count greater than 30 is : " + str(count)).  
count_greater30(l)

0

这是一个稍微长一点但适合初学者的详细解决方案:

from functools import reduce 
from statistics import mean

two_dim_array = [[1, 5, 7, 3, 2], [2, 4 ,1 ,6, 8]]

# convert two dimensional array to one dimensional array 
one_dim_array = reduce(list.__add__, two_dim_array)

arithmetic_mean = mean(one_dim_array)

exceeding_count = sum(i > arithmetic_mean for i in one_dim_array)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接