Python中的条件计数

时间:2009-11-19 15:54:26

标签: python arrays list count

不确定之前是否曾被问过,但我找不到明显的答案。我正在尝试计算列表中等于某个值的元素数。问题是这些元素不是内置类型。所以,如果我有

class A:
    def __init__(self, a, b):
        self.a = a
        self.b = b

stuff = []
for i in range(1,10):
    stuff.append(A(i/2, i%2))

现在我想要一个列表元素的计数,其字段b = 1.我提出了两个解决方案:

print [e.b for e in stuff].count(1)

print len([e for e in stuff if e.b == 1])

哪种方法最好?还有更好的选择吗?似乎count()方法不接受键(至少在Python 2.5.1版中。

非常感谢!

5 个答案:

答案 0 :(得分:41)

sum(x.b == 1 for x in L)

布尔(由x.b == 1等比较产生)也是int0的值为False1的值为True {1}},所以像求和这样的算法就可以了。

这是最简单的代码,但也许不是最快的(只有timeit可以告诉你肯定;-)。考虑(简化的情况,以适应命令行,但等效):

$ py26 -mtimeit -s'L=[1,2,1,3,1]*100' 'len([x for x in L if x==1])'
10000 loops, best of 3: 56.6 usec per loop
$ py26 -mtimeit -s'L=[1,2,1,3,1]*100' 'sum(x==1 for x in L)'
10000 loops, best of 3: 87.7 usec per loop

因此,对于这种情况,生成额外临时列表并检查其长度的“内存浪费”方法实际上比我更喜欢的更简单,更短,更节省内存的方法更快。列表值的其他组合,Python实现,在这种加速中“投入”的内存可用性等,当然会影响确切的性能。

答案 1 :(得分:14)

print sum(1 for e in L if e.b == 1)

答案 2 :(得分:2)

我更喜欢第二个,因为它只会在列表上循环一次。

如果您使用count(),您将循环遍历列表一次以获取b值,然后再次循环以查看其中有多少等于1.

可以使用reduce()

reduce(lambda x,y: x + (1 if y.b == 1 else 0),list,0)

The documentation告诉我们reduce()将:

  

将两个参数的函数累加到iterable的项目中,从左到右,以便将iterable减少为单个值。

因此,我们定义lambda,只有在列表项的b属性为1时,才会添加一个累计值。

答案 3 :(得分:0)

要隐藏reduce详细信息,您可以定义count功能:

def count(condition, stuff):
    return reduce(lambda s, x: \
                  s + (1 if condition(x) else 0), stuff, 0)

然后你可以通过提供计数条件来使用它:

n = count(lambda i: i.b, stuff)

答案 4 :(得分:-1)

给定输入

name = ['ball', 'jeans', 'ball', 'ball', 'ball', 'jeans']
price = [1, 4, 1, 1, 1, 4]
weight = [2, 2, 2, 3, 2, 2]

首先创建一个 defaultdict 来记录事件

from collections import defaultdict
occurrences = defaultdict(int)

增加计数

for n, p, w in zip(name, price, weight):
    occurrences[(n, p, w)] += 1

最后统计出现多次的那些(True会产生1)

print(sum(cnt > 1 for cnt in occurrences.values())