Python: counting the appearance of a List element in a list

I am trying to count the number of items in a list if such items are also lists. Order is also important.

[PSUEDOCODE] 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 of the important factors is that ['a', 'b', 'c'] != ['c', 'b', 'a']

I tried:

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

Which led to ['a', 'b', 'c'] = ['c', 'b', 'a'] , one thing I didn't want

I also tried:

 from collections import counter print( Counter( lst ) ) 

This only led to an error; since lists cannot be used as keys in dicts .

Is there any way to do this?

+5
source share
5 answers

You cannot have list as the key to the dict , because dictionaries only allow immutable objects as the key. Therefore, you need to first convert the objects to a tuple. Then you can use collection.Counter to get the amount 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}) 
+5
source

Lists are not hashed, but you can use tuples as workarounds:

 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 your own class that mimics the functionality of dictionary hash 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 
+5
source

just use collections.Counter for some equivalent type, but hashable: 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}) 
+5
source

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 need a dictionary from this, you can just change the last part to

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

Do not use the list as a variable name.

You can try this approach if you do not 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()))) 
+2
source

Source: https://habr.com/ru/post/1274432/


All Articles