1

I have 4 lists of dictionaries and each list contains 4 dictionaries. The lists look similar to this:

    A = [
     {'1': 150, '2': 160, '3': 140, '4': 110},
     {'1': 230, '2': 650, '3': 134, '4': 650},  
     {'1': 220, '2': 530, '3': 980, '4': 3450},  
     {'1': 150, '2': 160, '3': 440, '4': 110}]

    B = [
     {'1': 165, '2': 430, '3': 134, '4': 650},
     {'1': 64, '2': 650, '3': 345, '4': 340},  
     {'1': 220, '2': 650, '3': 340, '4': 134},  
     {'1': 150, '2': 160, '3': 234, '4': 2340}]

    C = [
     {'1': 678, '2': 430, '3': 134, '4': 650},
     {'1': 344, '2': 650, '3': 345, '4': 340},  
     {'1': 220, '2': 650, '3': 340, '4': 134},  
     {'1': 150, '2': 160, '3': 234, '4': 2340}]

    D = [
     {'1': 165, '2': 430, '3': 134, '4': 650},
     {'1': 64, '2': 650, '3': 345, '4': 340},  
     {'1': 220, '2': 650, '3': 340, '4': 134},  
     {'1': 150, '2': 160, '3': 234, '4': 1440}]

I would like to sum the values of the first dictionary of each list, where the keys are the same (so for key '1', then for '2', then for '3' and so on ...), together with the values of the first dictionary of the rest of the lists.
Then do the same for the second, third and fourth dictionary.

The expected outcome should be 4 dictionaries, that maintain the order of the keys while summing up the values for the keys that are the same.

I have tried the piece of code below:

for i in range (4):
    dict1 = A[i]
    dict2 = B[i]
    dict3 = C[i]
    dict4 = D[i]
# adding the values with common key      
    Cdict = Counter(dict1) + Counter(dict2) + Counter(dict3) + Counter(dict4)
    print(Cdict)

But the problem is that the order of the keys is changing:

Counter({'4': 2060, '2': 1450, '1': 1158, '3': 542})
Counter({'2': 2600, '4': 1670, '3': 1169, '1': 702})
Counter({'4': 3852, '2': 2480,'3': 2000, '1': 880})
Counter({'4': 6230, '3': 1142, '2': 640, '1': 600})
Pythoneer
  • 143
  • 8
  • Would be cool if you could reduce the size of that input dict to something easier to copy paste and check. It does not need to be that large. – timgeb Feb 28 '22 at 10:33
  • Your dictionaries are sorted by values try sorting them by keys. [How can I sort a dictionary by key?](https://stackoverflow.com/questions/9001509/how-can-i-sort-a-dictionary-by-key) – Thekingis007 Feb 28 '22 at 10:37
  • 1
    Value for key `'1'` in first Counter should be `150 + 165 + 678 + 165 = 1158`, no? – timgeb Feb 28 '22 at 10:55
  • 1
    @timgeb You are right - I corrected the typos. – Pythoneer Feb 28 '22 at 15:08

2 Answers2

1

IIUC this is pretty straight forward. You just write a function to sum up all values per key. Then apply it to the transposed list of lists of dicts.

def sum_by_key(dicts):
    result = {}

    for d in dicts:
        for k, v in d.items():
            result[k] = result.get(k, 0) + v

    return result

lists_of_dicts = [[{1:2, 3:4}, {1:10, 2:9}], [{3:8, 2:4}, {3:1, 2:5}]]
result = [sum_by_key(dicts) for dicts in zip(*lists_of_dicts)]

print(result)

(lists_of_dicts would be [A, B, C, D] with your variables)

Output:

[{1: 2, 3: 12, 2: 4}, {1: 10, 2: 14, 3: 1}]

edit: with your new sample data

lists_of_dicts = [A, B, C, D]
result = [sum_by_key(dicts) for dicts in zip(*lists_of_dicts)]
print(result)

produces

[{'1': 1158, '2': 1450, '3': 542, '4': 2060}, {'1': 702, '2': 2600, '3': 1169, '4': 1670}, {'1': 880, '2': 2480, '3': 2000, '4': 3852}, {'1': 600, '2': 640, '3': 1142, '4': 6230}]
timgeb
  • 76,762
  • 20
  • 123
  • 145
1

I use numpy. And btw, I think the result you gave is incorrect, mine from the code below is:

results:
{'1': 1158, '2': 1450, '3': 542, '4': 2060}
{'1': 702, '2': 2600, '3': 1169, '4': 1670}
{'1': 880, '2': 2480, '3': 2000, '4': 3852}
{'1': 600, '2': 640, '3': 1142, '4': 6230}

import numpy as np

A = [
    {'1': 150, '2': 160, '3': 140, '4': 110},
    {'1': 230, '2': 650, '3': 134, '4': 650},
    {'1': 220, '2': 530, '3': 980, '4': 3450},
    {'1': 150, '2': 160, '3': 440, '4': 110}]

B = [
    {'1': 165, '2': 430, '3': 134, '4': 650},
    {'1': 64, '2': 650, '3': 345, '4': 340},
    {'1': 220, '2': 650, '3': 340, '4': 134},
    {'1': 150, '2': 160, '3': 234, '4': 2340}]

C = [
    {'1': 678, '2': 430, '3': 134, '4': 650},
    {'1': 344, '2': 650, '3': 345, '4': 340},
    {'1': 220, '2': 650, '3': 340, '4': 134},
    {'1': 150, '2': 160, '3': 234, '4': 2340}]

D = [
    {'1': 165, '2': 430, '3': 134, '4': 650},
    {'1': 64, '2': 650, '3': 345, '4': 340},
    {'1': 220, '2': 650, '3': 340, '4': 134},
    {'1': 150, '2': 160, '3': 234, '4': 1440}]

group_list = [A,B,C,D]
items_num = len(A)
results =  []

for i in range(items_num):
    cur_item_dict = dict()

    for key in A[0].keys():
        cur_item_dict[key] = np.sum([ls[i][key]  for j, ls in enumerate(group_list)])

    results.append(cur_item_dict)

print('results:')
for res in results:
print(res)
Jason
  • 3,166
  • 3
  • 20
  • 37