我不确定之前有人问过这个问题,但我找不到明显的答案。我正在尝试计算列表中等于某个值的元素的数量。问题是这些元素不是内置类型。所以如果我有
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中是这样。
非常感谢!
发布于 2009-11-20 00:03:10
sum(x.b == 1 for x in L)
一个布尔值(如通过比较得到的x.b == 1
)也是一个int
,值为0
对于False
,1
对于True
,所以像求和这样的算术工作得很好。
这是最简单的代码,但可能不是最快的(仅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实现、用于“投资”此加速的内存可用性等都会影响确切的性能。
发布于 2009-11-19 23:57:23
print sum(1 for e in L if e.b == 1)
发布于 2009-11-19 23:58:37
我更喜欢第二个,因为它只在列表上循环一次。
如果您使用count()
您只需遍历列表一次,即可获得b
值,然后再次循环它以查看它们中有多少等于1。
一种巧妙的方式可以使用
reduce()reduce(lambda x,y: x + (1 if y.b == 1 else 0),list,0)
documentatio告诉我们reduce()
将:
将两个参数的函数从左到右累加到iterable的项上,从而将iterable减少为一个值。
所以我们定义一个lambda
仅当列表项的b
属性为% 1。
https://stackoverflow.com/questions/1764309
复制相似问题