简体   繁体   中英

Python. How to conveniently count the frequence of lists in a collection of lists

I have a list of list.

e.g. list_a = [[1,2,3], [2,3], [4,3,2], [2,3]]

I want to count them like

[1,2,3]: 1
[2,3]: 2
[4,3,2]: 1

There is a library Counter in collections but not for unhashable elements like list. Currently, I just try to use other indirect ways for example transfer the list [1,2,3] into a string "1_2_3" to do that. Is there any other way can enable the count on the list directly?

Not the prettiest way to do it, but this works:

list_a = [[1,2,3], [2,3], [4,3,2], [2,3]]
counts = {} 

for x in list_a: 
    counts.setdefault(tuple(x), list()).append(1) 
for a, b in counts.items(): 
    counts[a] = sum(b) 
print(counts) 
{(2, 3): 2, (4, 3, 2): 1, (1, 2, 3): 1}

A possible approach to do this job is using a dict .

  1. Create a empty dict
  2. Iterate over the list using a for loop.
  3. For each element (iteration), check if the dict contains it.
  4. If it doesn't, save it in the dict as a key. The value will be the occurrence counter.
  5. If it does, just increment its value.

Possible implementation:

occurrence_dict = {}

for list in list_a:
    if (occurrence_dict.get(str(list), False)):
        occurence_dict[str(list)] += 1
    else:
        ocorrence_dict[str(list)] = 1

print(occurence_dict)

You can achieve it easily, by using tuple instead of list

c = Counter(tuple(item) for item in list_a)
# or
c = Counter(map(tuple, list_a))

# Counter({(2, 3): 2, (1, 2, 3): 1, (4, 3, 2): 1})
# exactly what you expected
(1, 2, 3) 1
(2, 3) 2
(4, 3, 2) 1

Way 1

Through the indexes of repeatable lists

list_a = [[1,2,3], [2,3], [4,3,2], [2,3], [1,2,3]]  # just add some  data

# step 1
dd = {i:v for i, v in enumerate(list_a)}
print(dd)

Out[1]:
{0: [1, 2, 3], 1: [2, 3], 2: [4, 3, 2], 3: [2, 3], 4: [1, 2, 3]}

# step 2
tpl = [tuple(x for x,y in dd.items() if y == b) for a,b in dd.items()]
print(tpl)

Out[2]:
[(0, 4), (1, 3), (2,), (1, 3), (0, 4)]  # here is the tuple of indexes of matching lists

# step 3
result = {tuple(list_a[a[0]]):len(a) for a in set(tpl)}
print(result)

Out[3]:
{(4, 3, 2): 1, (2, 3): 2, (1, 2, 3): 2}

Way 2

Through converting nested lists to tuples

{i:[tuple(a) for a in list_a].count(i) for i in [tuple(a) for a in list_a]}

Out[1]:
{(1, 2, 3): 2, (2, 3): 2, (4, 3, 2): 1}
arr = [[1,2,3], [2,3], [4,3,2], [2,3], [4,3,2]]
counter = dict()
for a in arr:
    k = hash(tuple(a))
    if k in counter: counter[k][1] += 1
    else: counter[k] = [a, 1]
print(counter)

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