Python:在对象列表中获得两个布尔属性频率的最有效方法?

2024-04-25 06:09:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个User对象,有两个布尔属性,如下所示:

class User(object):
  def __init__(self, a, b):
    self.a = a  # Always a bool
    self.b = b  # Always a bool

我有一个这些对象的列表,名为user_list,我想得到有多少对象具有a==True、a==False、b==True和b==False的频率计数。在

我最初的方法是使用集合。计数器,但这需要在列表中循环两次:

^{pr2}$

我也想过只使用4个计数器,但这很难看,而且没有Python的感觉:

a_true_count = 0
a_false_count = 0
b_true_count = 0
b_false_count = 0
for u in user_list:
  if u.a:
    a_true_count += 1
  else:
    a_false_count += 1
  if u.b:
    b_true_count += 1
  else:
    a_false_count += 1
print a_true_count, a_false_count, b_true_count, b_false_count

有没有更有效的方法?输出可以是任何东西:4个单独的变量,一个包含值的dict,一个list,tuple,任何东西,只要它包含这4个值。在

提前谢谢!在


Tags: 对象方法selffalsetrue列表count计数器
3条回答

为什么不使用两个计数器,并从user_list的长度中减去来找到另外两个值呢?在

a_false_count = len(user_list) - a_true_count

b_false_count = len(user_list) - b_true_count

这种显式循环可能是最有效的解决方案,但如果您正在寻找更简洁的代码,您可以尝试filter()

a_false_count = len(filter(lambda x: x.a,user_list))
b_false_count = len(filter(lambda x: x.b,user_list))

我认为使用collections.Counter是正确的想法,只需使用一个Counter和一个循环,以更通用的方式进行:

from collections import Counter

user_list = [User(True, False), User(False, True), User(True, True), User(False, False)]
user_attr_count = Counter()

for user in user_list:
    user_attr_count['a_%s' % user.a] += 1
    user_attr_count['b_%s' % user.b] += 1

print user_attr_count
# Counter({'b_False': 2, 'a_True': 2, 'b_True': 2, 'a_False': 2})
from collections import Counter

c = Counter()
for u in user_list:
    c['a'] += u.a
    c['b'] += u.b

print c['a'], len(user_list) - c['a'], c['b'], len(user_list) - c['b']

相关问题 更多 >