Make a dictionary of two lists using Counter object

I have the following list:

name = ["Anne", "Jack", "Mary"]

      

I also have a nested list where each item is a different list and is associated with the name present in the index name

. This is shown below:

n1 = [[0, 0, 3], [0, 5, 5], [1, 3, 3]]

      

So, for 'Anne'

, the first item in the list name

, the associated list of n1

is the first item [0, 0, 3]

.

Likewise, for the "Jack"

second item in the list name

, the associated list of n1

is the second item, [0, 5, 5]

and so on.

I want to count the number of each number in each element n1

and associate it with the names in a list name

in dictionary format.

So, I want my output to look like this:

{'Anne': {'0': 2, '3': 1}, 'Jack': {'0': 1, '5': 2}, 'Mary': {'1': 1, '3': 2}}

      

I've tried the following:

      from collections import Counter
      clust = {}
      for val in name:
         clust[val] = {}
         for e in n1:
             wc = Counter(str(e1) for e1 in e)
             clust[val] = dict(wc)

      

But this gives me the result:

clust = {'Anne': {'1': 1, '3': 2}, 'Jack': {'1': 1, '3': 2}, 'Mary': {'1': 1, '3': 2}}

      

This is not true. How do I achieve the result I want?

+3


source to share


5 answers


You need to map data from n1

to each item in name

; the simplest way is zip

:

>>> from collections import Counter
>>> name = ["Anne", "Jack", "Mary"]
>>> n1 = [[0,0,3], [0,5,5], [1,3,3]]
>>> {name_: Counter(data) for name_, data in zip(name, n1)}
{'Anne': Counter({0: 2, 3: 1}), 'Jack': Counter({5: 2, 0: 1}), 'Mary': Counter({3: 2, 1: 1})}

      

(Note the use of "vocabulary comprehension", see docs .)



If keys in strings Counter

are critical, you can use map

to convert integers before counting:

>>> {name_: Counter(map(str, data)) for name_, data in zip(name, n1)}
{'Anne': Counter({'0': 2, '3': 1}), 'Jack': Counter({'5': 2, '0': 1}), 'Mary': Counter({'3': 2, '1': 1})}

      

+4


source


For each name, the loop loops for e in n1:

over all n1 elements, creating a counter for each of them and setting clust[val]

to the result. Thus, it clust[val]

ends up as a result of only the last item in the n1

.

You should use zip()

to concatenate the name of the two lists and n1 into one, or probably better, a list of names and the resulting counters from n1. zip()

returns tuples with elements taken from both lists ( zip([1, 2], ['a', 'b']) becomes [(1, 'a'), (2, 'b')]

. You can make dict

from such tuples directly.



So:

clust = dict(zip(name, [Counter(e) for e in n1]))

      

+2


source


Just use the index value of the list name

to count the items in the sublist n1

. This can be done using enumerate(name)

. It returns the value and its index. Use this returned index to count the items in the substring n1

that match the item in name

.

>>> from collections import Counter
>>> name = ["Anne", "Jack", "Mary"]
>>> n1 = [[0,0,3], [0,5,5], [1,3,3]]
>>> clust = {}
>>> for i,val in enumerate(name):
...     wc = Counter(str(e1) for e1 in n1[i])
...     clust[val] = dict(wc)
... 
>>> clust
{'Anne': {'0': 2, '3': 1}, 'Jack': {'0': 1, '5': 2}, 'Mary': {'1': 1, '3': 2}}

      

+1


source


You need to do it like this:

from collections import Counter
name = ["Anne", "Jack", "Mary"]
n1 = [[0,0,3], [0,5,5], [1,3,3]]
clust = {name[i]: Counter(n1[i]) for i in range(len(name))}

      

Output:

{'Anne': Counter({0: 2, 3: 1}), 'Jack': Counter({5: 2, 0: 1}), 'Mary': Counter({3: 2, 1: 1})}

0


source


Here's one liner to get the result you want:

zip(name, [dict(Counter(z)) for z in [[str(y) for y in x] for x in n1]])

      

To break it down:

  • [[str(y) for y in x] for x in n1]

    converts n1 elements to list
  • dict(Counter(z))

    create a counting list for each list n1
  • zip

    combines two lists
0


source







All Articles