Olle
Olle

Reputation: 107

Python: Counting occurrences of List element within List

I'm trying to count the number of occurrences of elements within a list, if such elements are also lists. The order is also important.

[PSEUDOCODE]

lst = [ ['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'c'], ['c', 'b', 'a'] ]
print( count(lst) )


> { ['a', 'b', 'c'] : 2, ['d', 'e', 'f']: 1, ['c', 'b', 'a']: 1 }

One important factor is that ['a', 'b', 'c'] != ['c', 'b', 'a']

I have tried:

from collections import counter
print( Counter([tuple(x) for x in lst]) )
print( [[x, list.count(x)] for x in set(lst)] )

Which both resulted in ['a', 'b', 'c'] = ['c', 'b', 'a'], one thing i didn't want

I also tried:

from collections import counter
print( Counter( lst ) )

Which only resulted in error; since lists can't be used as keys in dicts.

Is there a way to do this?

Upvotes: 7

Views: 3927

Answers (5)

user9158931
user9158931

Reputation:

Don't Use list as variable name.

You can try this approach if you don't want to use any module :

list_1 = [ ['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'c'], ['c', 'b', 'a'] ]

track={}

for i in list_1:
    if tuple(i) not in track:
        track[tuple(i)]=1
    else:
        track[tuple(i)]+=1

print(track)

outoput:

{('a', 'b', 'c'): 2, ('d', 'e', 'f'): 1, ('c', 'b', 'a'): 1}

You can also use default dict:

list_1 = [ ['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'c'], ['c', 'b', 'a'] ]

track={}

import collections
d=collections.defaultdict(list)

for j,i in enumerate(list_1):
    d[tuple(i)].append(j)

print(list(map(lambda x:{x:len(d[x])},d.keys())))

Upvotes: 2

Ajax1234
Ajax1234

Reputation: 71451

Lists are not hashable, but you can use tuples as a workaround:

l = [ ['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'c'], ['c', 'b', 'a'] ]
new_l = list(map(tuple, l))
final_l = {a:new_l.count(a) for a in new_l}

Output:

{('a', 'b', 'c'): 2, ('d', 'e', 'f'): 1, ('c', 'b', 'a'): 1}

Or, if you really want to use lists, you can create a custom class to mimic the functionality of a dictionary hashing lists:

class List_Count:
    def __init__(self, data):
       new_data = list(map(tuple, data))
       self.__data = {i:new_data.count(i) for i in new_data}
    def __getitem__(self, val):
       newval = [b for a, b in self.__data.items() if list(a) == val]
       if not newval:
          raise KeyError("{} not found".format(val))
       return newval[0]
    def __repr__(self):
       return "{"+"{}".format(', '.join("{}:{}".format(list(a), b) for a, b in self.__data.items()))+"}"

l = List_Count([ ['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'c'], ['c', 'b', 'a'] ])
print(l)
print(l[['a', 'b', 'c']])

Output:

{['a', 'b', 'c']:2, ['d', 'e', 'f']:1, ['c', 'b', 'a']:1}
2

Upvotes: 6

dangee1705
dangee1705

Reputation: 3510

Another implementation with lists

l1 = [["a", "b", "c"], ["b", "c", "d"], ["a", "b", "c"], ["c", "b", "a"]]

def unique(l1):
    l2 = []
    for element in l1:
        if element not in l2:
            l2.append(element)
    return l2

l2 = unique(l1)
for element in l2:
    print(element, l1.count(element))

and if you want an dictionary from that you can just change the last part to

output = {element:l1.count(element) for element in unique(l1)}

Upvotes: 2

Jean-François Fabre
Jean-François Fabre

Reputation: 140148

just use collections.Counter on some equivalent type but hashable: the tuple:

import collections

lst = [ ['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'c'], ['c', 'b', 'a'] ]

c = collections.Counter(tuple(x) for x in lst)

print(c)

result:

Counter({('a', 'b', 'c'): 2, ('d', 'e', 'f'): 1, ('c', 'b', 'a'): 1})

Upvotes: 6

Moinuddin Quadri
Moinuddin Quadri

Reputation: 48057

You can't have list as a key to the dict because dictionaries only allows immutable objects as it's key. Hence you need to firstly convert your objects to tuple. Then you may use collection.Counter to get the count of each tuple as:

>>> from collections import Counter
>>> my_list = [ ['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'c'], ['c', 'b', 'a'] ]

#            v to type-cast each sub-list to tuple
>>> Counter(tuple(item) for item in my_list)
Counter({('a', 'b', 'c'): 2, ('d', 'e', 'f'): 1, ('c', 'b', 'a'): 1})

Upvotes: 6

Related Questions