简体   繁体   中英

Count the number of times an item occurs in each nested list

So I have a list of whether or not people won, drew or lost a game over each time they played:

scores = [["win","lose","win"],["win","win"],["draw","win"],["lose"]]

And I want to get a count of 'win' / 'lose' / 'draw' for each sublist

Can I do this using a dictionary?

eg dict= {[win:2, draw:0, lose:1],[win:2, draw:0, lose:0].....}

I tried counting and placing in a list by doing this:

countlose=0
for sublist in scores:
    for item in sublist:
        for item in range(len(sublist)):
            if item=="lose":
                countlose+=1
print(countlose)

But this just returned 0

Let me know how you would solve the problem

Your desired result isn't valid syntax. Most likely you want a list of dictionaries.

collections.Counter only counts values in an iterable; it does not count externally supplied keys unless you supply additional logic.

In this case, you can use a list comprehension, combining with an empty dictionary:

from collections import Counter

scores = [["win","lose","win"],["win","win"],["draw","win"],["lose"]]

empty = dict.fromkeys(('win', 'lose', 'draw'), 0)

res = [{**empty, **Counter(i)} for i in scores]

[{'draw': 0, 'lose': 1, 'win': 2},
 {'draw': 0, 'lose': 0, 'win': 2},
 {'draw': 1, 'lose': 0, 'win': 1},
 {'draw': 0, 'lose': 1, 'win': 0}]

Can I do this using a dictionary?

You can use collections.Counter , which is a subclass of dict for counting hashable objects:

>>> from collections import Counter
>>> scores = [['win', 'lose', 'win'], ['win', 'win'], ['draw', 'win'], ['lose']]
>>> counts = [Counter(score) for score in scores]
>>> counts
[Counter({'win': 2, 'lose': 1}), Counter({'win': 2}), Counter({'draw': 1, 'win': 1}), Counter({'lose': 1})]

To add zero counts for missing keys you can use an additional loop:

>>> for c in counts:
...     for k in ('win', 'lose', 'draw'):
...         c[k] = c.get(k, 0)
... 
>>> counts
[Counter({'win': 2, 'lose': 1, 'draw': 0}), Counter({'win': 2, 'lose': 0, 'draw': 0}), Counter({'draw': 1, 'win': 1, 'lose': 0}), Counter({'lose': 1, 'win': 0, 'draw': 0})]

Alternatively, you could wrap the counters with collections.defaultdict :

>>> counts = [defaultdict(int, Counter(score)) for score in scores]
>>> counts
[defaultdict(<class 'int'>, {'win': 2, 'lose': 1}), defaultdict(<class 'int'>, {'win': 2}), defaultdict(<class 'int'>, {'draw': 1, 'win': 1}), defaultdict(<class 'int'>, {'lose': 1})]
>>> counts[0]['draw']
0

You could apply a list comprehension for every sublist from your given list.

Also, declare your own counter function which counts the number of appearances of one item from win , lose or draw .

scores = [["win","lose","win"],["win","win"],["draw","win"],["lose"]]
def get_number(sublist):
  counter = {'win': 0, 'draw' : 0, 'lose': 0}
  for item in sublist:
    counter[item] += 1
  return counter

result = [get_number(sublist) for sublist in scores]

Output

[{'win': 2, 'draw': 0, 'lose': 1}, 
 {'win': 2, 'draw': 0, 'lose': 0}, 
 {'win': 1, 'draw': 1, 'lose': 0}, 
 {'win': 0, 'draw': 0, 'lose': 1}]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM