3

次のように、2 つのブール値プロパティを持つユーザー オブジェクトがあります。

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 を持つオブジェクトの頻度を取得したいと考えています。

私の最初のアプローチは collections.Counter を使用することでしたが、それにはリストを 2 回ループする必要があります。

a_count = collections.Counter(u.a for u in user_list)
b_count = collections.Counter(u.b for u in user_list)
print a_count[True], a_count[False], b_count[True], b_count[False]

4 つのカウンターだけを使用することも考えましたが、それは見苦しく、pythonic とは感じません。

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、リスト、タプルなど、4 つの値が含まれている限り何でもかまいません。

前もって感謝します!

4

6 に答える 6

3

a を使用するのは正しい考えだと思います。単一および単一のループを使用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})
于 2013-03-22T00:19:10.930 に答える
2

2 つのカウンターを使用して、 の長さから減算してuser_list、他の 2 つの値を見つけてみませんか?

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))
于 2013-03-22T00:05:05.133 に答える
1

ビットマスキングを使用できます:

def count(user_list,mask):
    return Counter((u.a<<1 | u.b)&mask for u in user_list)

a=0b10
b=0b01
aANDb=0b11
print count(user_list,aANDb)
于 2013-03-22T00:21:51.877 に答える