How to Count Occurrence of Unique Values Inside a List

How to get unique values with respective occurrence count from a list in Python?

If your items are grouped (i.e. similar items come together in a bunch), the most efficient method to use is itertools.groupby:

>>> [(g[0], len(list(g[1]))) for g in itertools.groupby(['a', 'a', 'b', 'b', 'b'])]
[('a', 2), ('b', 3)]

How do I count the occurrences of a list item?

If you only want a single item's count, use the count method:

>>> [1, 2, 3, 4, 1, 4, 1].count(1)
3


Important: this is very slow if you are counting multiple different items

Each count call goes over the entire list of n elements. Calling count in a loop n times means n * n total checks, which can be catastrophic for performance.

If you want to count multiple items, use Counter, which only does n total checks.

Count of each unique element in a list

If you want to sort depending on the ul list, you can use list comprehension like:

l = ['India', 'China', 'China', 'Japan', 'USA', 'India', 'USA']
ul = ['India', 'China', 'Japan', 'USA']
result = sorted([(x, l.count(x)) for x in ul], key=lambda y: y[1])
for elem in result:
print '{} {}'.format(elem[0], elem[1])

output:

Japan 1
India 2
China 2
USA 2

And if you want to sort by alphabet after sorting by count, you can change result to the following:

result = sorted(sorted([(x, l.count(x)) for x in ul]), key=lambda y: y[1])

output:

Japan 1
China 2
India 2
USA 2

How to get the sums of unique values with respective occurrence count from a list in Python?

Since you are using Numpy, you can just multiply the results you already have from np.unique:

import numpy as np

L = [1,1,1,2,2,3,3,3]
uniq, counts = np.unique(L, return_counts=True)

uniq * counts
# array([3, 4, 9])

Count number of occurrences of each unique element in a list in ansible

  • Use community.general.counter if you can install latest collection Community.General
list_counter: "{{ list|community.general.counter }}"

gives the expected result

list_counter:
5.8.3: 1
5.8.4: 2
5.9.2: 3


  • If you're not able to install the collection take the code and create a custom filter plugin
shell> cat filter_plugins/my_counter.py 
# -*- coding: utf-8 -*-
# Copyright (c) 2021, Remy Keil <remy.keil@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from ansible.errors import AnsibleFilterError
from ansible.module_utils.common._collections_compat import Sequence
from collections import Counter

def my_counter(sequence):
''' Count elements in a sequence. Returns dict with count result. '''
if not isinstance(sequence, Sequence):
raise AnsibleFilterError('Argument for community.general.counter must be a sequence (string or list). %s is %s' %
(sequence, type(sequence)))

try:
result = dict(Counter(sequence))
except TypeError as e:
raise AnsibleFilterError(
"community.general.counter needs a sequence with hashable elements (int, float or str) - %s" % (e)
)
return result

class FilterModule(object):
''' Ansible counter jinja2 filters '''

def filters(self):
filters = {
'my_counter': my_counter,
}

return filters

Use it

list_counter: "{{ list|my_counter }}"

  • The declaration below gives the same result if you don't want to use collections or write a custom filter
list_counter: "{{ dict(data|
unique|
zip(data|
json_query('[].{key:@, value: `1`}')|
groupby('key')|
map(attribute=1)|
map('map', attribute='value')|
map('sum')|list)) }}"


Related Topics



Leave a reply



Submit