I have a list with individual dicts, like so:
dct = [{ 'winner': 'Person A' }, { 'winner': 'Person B' }, { 'winner': 'Person B' } ...]
(the dicts have other properties, they're just not relevant).
I want to know how many times the winner was a particular string. I could do something like this:
aWins = sum((1 if d['winner'] == 'Person A' else 0) for d in dct)
then do the same for 'Person B', and maybe possibly 'Person C' if that ever comes up, etc.
However, that doesn't strike me as particularly neat or pythonic. I'm still learning all the pythonic ways of doing things (I daily drive JS, so usually I'd be doing this via reduce), so is it possible to do this more neatly? Ideally, the output is a dict that looks something like this:
{ 'Person A': 40, 'Person B': 60 }
CodePudding user response:
You can use operator.itemgetter
as a mapper to extract values of the winner
key of each dict. Use collections.Counter
to count the number of occurrences of each value:
from collections import Counter
from operator import itemgetter
d = [{'winner': 'A'}, {'winner': 'B'}, {'winner': 'B'}]
print(dict(Counter(map(itemgetter('winner'), d))))
This outputs:
{'A': 1, 'B': 2}
CodePudding user response:
More efficient:
lst = [x['winner'] for x in dct]
print({k:lst.count(k) for k in lst})
# print({k:lst.count(k) for k in set(lst)}) # Alternatively, time-efficient but needs key sorting
Output:
{'A': 1, 'B': 2}
Highly inefficient, yet a one-liner:
dct = [{ 'winner': 'A' }, { 'winner': 'B' }, { 'winner': 'B' }]
print({k:[x['winner'] for x in dct].count(k) for k in [x['winner'] for x in dct]})
Output:
{'A': 1, 'B': 2}
CodePudding user response:
You can use pandas:
import pandas as pd
dictionary = [{ 'winner': 'Person A' }, { 'winner': 'Person B' }, { 'winner': 'Person B' }]
dataframe = pd.DataFrame.from_dict(dictionary)
number = dataframe["winner"].value_counts()
Function value_counts counts occurrences of a value (in this case, a string).
Output:
Person B 2
Person A 1
Name: winner, dtype: int64
CodePudding user response:
Using pandas:
import pandas as pd
my_dict = [
{ 'winner': 'A' },
{ 'winner': 'B' },
{ 'winner': 'B' },
{ 'winner': 'B' }
]
pd.DataFrame(data=my_dict) \
.groupby("winner") \
.agg(counts = ("winner", "count")) \
.to_dict()["counts"]
# {'A': 1, 'B': 3}
CodePudding user response:
The way I would do it is to loop once over the entire list:
from collections import defaultdict
num_wins = defaultdict(int)
for d in dicts:
num_wins[d['winner']] = 1
Just for fun, a O(nk) one-liner, where k is the number of possible persons:
persons = list("ABC")
num_wins = {
sum((1 if d['winner'] == person else 0) for d in dict)
for person in persons
}
CodePudding user response:
you can iterate over the list, and see if the winner
present in the iterator dict object , if yes then save that value in resultant dictionary and make count over there.
dict_ = [{ 'winner': 'Person A' }, { 'winner': 'Person B' }, { 'winner': 'Person B' }]
from collections import defaultdict as dd
result = dd(int)
for dic in dict_:
if 'winner' in dic:
result[dic['winner']] =1
print(result)
# defaultdict(<class 'int'>, {'Person A': 1, 'Person B': 2})
CodePudding user response:
How about this?
dct = [{ 'winner': 'Person A' }, { 'winner': 'Person B' }, { 'winner': 'Person B' }]
cnt_a = 0
cnt_b = 0
for i in dct:
if str(i).count('A') >0:
cnt_a = 1
elif str(i).count('B') >0:
cnt_b = 1
result = {'Person A' : cnt_a, 'Person B' : cnt_b }
result
Output:
{'Person A': 1, 'Person B': 2}