How to create a dictionary with specific defined value behavior

Suppose I have two lists:

l1 = [['b', (1, 1)], ['b', (1, 2)], ['b', (1, 3)], ['a', (1, 5)], ['b', (2, 1)], ['b',(3, 1)]] l2 = ['A','B','C'] 

How can I create a dictionary in this format?

 dct = {'A': len(sublist1), 'B': len(sublist2), 'C' : len(sublist3)} 

Where

 sublist1 = [['b', (1, 1)], ['b', (1, 2)], ['b', (1, 3)], ['a', (1, 5)]] sublist2 = [['b', (2, 1)]] sublist3 = [['b',(3, 1)]] 

what happens if my l1 is given below:

 ls1 = [[(1, 1), (1, 2), (1, 3), (1, 4), (2, 1), (2, 2)]] 

then my conclusion should be:

 dct = {'A': len(sublist1), 'B': len(sublist2)} 

Where

 sublist1 = [[(1, 1),(1, 2),(1, 3),(1, 4)]] sublist2 = [[(2, 1),(2, 2),(2, 3)]] 

Is it possible to solve a general problem in a general way?

+4
source share
5 answers

It works:

 from itertools import groupby key = lambda x: x[1][0] lens = [len(list(g)) for k, g in groupby(sorted(l1, key=key), key=key)] dct = dict(zip(l2, lens)) 

I hope I understood correctly when I assumed that A matches 1, B matches 2, etc.

Re: OP editing

I do not know where the (2, 3) element comes from in your sublist2 , I assume this is an error. In addition, I assume that the only list of ls1 elements should actually be a direct container of tuples, since using nested lists is impractical here. If so, then here is my suggestion for a general solution:

 from itertools import groupby from string import ascii_uppercase key = lambda x: x[0] lens = [len(list(g)) for k, g in groupby(sorted(l1, key=key), key=key)] dct = dict(zip(ascii_uppercase, lens)) 

So, no big changes. The zip function with given arguments of unequal length returns a list with the same length as the shortest argument, and this behavior suits us in this situation.

Keep in mind that if there are more than 26 different values ​​for the first element of the tuple, then this solution will break and simply ignore any values ​​that exceed the 26th.

+8
source
 groups = itertools.groupby(l1, lambda x: x[1][0]) dict(zip(l2, map(len, (list(list(g[1]) for g in groups))))) 

leads to

 {'A': 4, 'B': 1, 'C': 1} 
+1
source
 >>> l1 = [['b', (1, 1)], ['b', (1, 2)], ['b', (1, 3)], ['a', (1, 5)], ['b', (2, 1)], ['b',(3, 1)]] >>> dct = {'A': 0, 'B' : 0, 'C': 0} >>> translation = {1: 'A', 2: 'B', 3: 'C'} >>> for list_ in l1: ... letter, tuple_ = list_ ... num1, num2 = tuple_ ... t = translation[num1] ... dct[t] += 1 ... >>> dct {'A': 4, 'C': 1, 'B': 1} 
0
source
 from collections import defaultdict lst = [['b', (1, 1)], ['b', (1, 2)], ['b', (1, 3)], ['a', (1, 5)], ['b', (2, 1)], ['b', (3, 1)]] #test list def mapping(x): """ convert 1 to A, 2 to B and so on """ return chr(ord('A')+x-1) dct = defaultdict(int) for _, tple in lst: k, _ = tple dct[ mapping(k) ] += 1 print (dct) # defaultdict(<type 'int'>, {'A': 4, 'C': 1, 'B': 1}) 
0
source

I would do this:

 dct = dict((k, len([l for l in l1 if l[1][0] == i + 1])) for i, k in enumerate(l2)) 
-1
source

All Articles