7

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?

3
  • 1
    So what have you tried so far? Commented Jan 1, 2018 at 20:47
  • 2
    tuple(['a', 'b', 'c']) == tuple(['c', 'b', 'a']) gives me False Commented Jan 1, 2018 at 20:51
  • Since "lists can't be used as keys in dicts", your desired output is impossible; what do you want instead? Commented Jan 1, 2018 at 20:59

5 Answers 5

6

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})
Sign up to request clarification or add additional context in comments.

Comments

6

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})

Comments

6

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

1 Comment

The tuple workaround is nice to get an almost one-liner solution!
2

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)}

Comments

2

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())))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.