Python: Most efficient way to get two Boolean property frequencies in a list of objects?
--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Game 5 Looping
--
Chapters
00:00 Python: Most Efficient Way To Get Two Boolean Property Frequencies In A List Of Objects?
01:06 Accepted Answer Score 2
01:37 Answer 2 Score 3
01:57 Answer 3 Score 1
02:09 Answer 4 Score 1
02:15 Thank you
--
Full question
https://stackoverflow.com/questions/1556...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #list #properties #frequency
#avk47
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Game 5 Looping
--
Chapters
00:00 Python: Most Efficient Way To Get Two Boolean Property Frequencies In A List Of Objects?
01:06 Accepted Answer Score 2
01:37 Answer 2 Score 3
01:57 Answer 3 Score 1
02:09 Answer 4 Score 1
02:15 Thank you
--
Full question
https://stackoverflow.com/questions/1556...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #list #properties #frequency
#avk47
ANSWER 1
Score 3
I think using a collections.Counter is the right idea, just do it in a more generic way with a single Counter and single loop:
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})
ACCEPTED ANSWER
Score 2
Why not use two counters, and subtract from the length of user_list to find the other two values?
a_false_count = len(user_list) - a_true_count
b_false_count = len(user_list) - b_true_count
Explicitly looping like that is probably the most efficient solution time-wise, but if you're looking for something a little more succinct code-wise, you might try filter():
a_false_count = len(filter(lambda x: x.a,user_list))
b_false_count = len(filter(lambda x: x.b,user_list))
ANSWER 3
Score 1
You could use bit masking:
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)
ANSWER 4
Score 1
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']