Вы можете использовать вложенный defaultdict
из Counter
для подсчета:
from collections import defaultdict, Counter
from pprint import pprint
input_data = [
{'A': 'A1', 'B': 'B1'},
{'A': 'A1', 'B': 'B1'},
{'A': 'A1', 'B': 'B2'},
{'A': 'A2', 'B': 'B3'},
{'A': 'A2', 'B': 'B2'},
{'A': 'A1', 'B': 'B1'},
{'A': 'A1', 'B': 'B1'},
{'A': 'A1', 'B': 'B2'},
{'A': 'A1', 'B': 'B1'}
]
d = defaultdict(lambda : defaultdict(Counter))
mapping = {'A': 'B', 'B': 'A'}
for data in input_data:
for k, v in data.items():
reverse_key = data[mapping[k]]
d[k][v][reverse_key] += 1
pprint(d)
Выход:
defaultdict(<function <lambda> at 0x0000021CB4665160>,
{'A': defaultdict(<class 'collections.Counter'>,
{'A1': Counter({'B1': 5, 'B2': 2}),
'A2': Counter({'B3': 1, 'B2': 1})}),
'B': defaultdict(<class 'collections.Counter'>,
{'B1': Counter({'A1': 5}),
'B2': Counter({'A1': 2, 'A2': 1}),
'B3': Counter({'A2': 1})})})
Вы также можете использовать вложенный defaultdict
без Counter
:
d = defaultdict(lambda : defaultdict(lambda : defaultdict(int)))
, который даст почти то же самое:
defaultdict(<function <lambda> at 0x000001D544AD5160>,
{'A': defaultdict(<function <lambda>.<locals>.<lambda> at 0x000001D546AB89D0>,
{'A1': defaultdict(<class 'int'>,
{'B1': 5,
'B2': 2}),
'A2': defaultdict(<class 'int'>,
{'B2': 1,
'B3': 1})}),
'B': defaultdict(<function <lambda>.<locals>.<lambda> at 0x000001D546AB8A60>,
{'B1': defaultdict(<class 'int'>, {'A1': 5}),
'B2': defaultdict(<class 'int'>,
{'A1': 2,
'A2': 1}),
'B3': defaultdict(<class 'int'>, {'A2': 1})})})
Примечание: Вышеуказанное не включает 0
значений. Это не имеет значения, потому что даже если вы сделаете d['A']['A1']['B3']
, вы получите 0
.
Также defaultdict
и Counter
являются подклассами dict
, поэтому они могут рассматриваться как обычные словари ,