from collections import defaultdict
from json import dumps
from pprint import pprint
last_data = [{'country': 'USA', 'cases': 10425, 'deaths': 1704, 'recovered': 2525, 'active': 100027},
{'country': 'Australia', 'cases': 3045, 'deaths': 1704, 'recovered': 2525, 'active': 100027},
{'country': 'Germany', 'cases': 6025, 'deaths': 1704, 'recovered': 2525, 'active': 100027}]
current_data = [{'country': 'USA', 'cases': 10425, 'deaths': 1704, 'recovered': 2525, 'active': 100027},
{'country': 'Australia', 'cases': 3046, 'deaths': 1704, 'recovered': 2525, 'active': 100028},
{'country': 'Germany', 'cases': 6026, 'deaths': 1706, 'recovered': 2525, 'active': 100026}]
def list_dicts_to_nested_dict(key, lst):
return {dic[key]: {k: v for k, v in dic.items() if k != key} for dic in lst}
def defaultdict_to_dict(df):
result = {}
for k, v in df.items():
if isinstance(v, defaultdict):
result[k] = dict(v)
defaultdict_to_dict(v)
return dict(result)
last_data_dict = list_dicts_to_nested_dict('country', last_data)
current_data_dict = list_dicts_to_nested_dict('country', current_data)
result = defaultdict(lambda: defaultdict(dict))
for country in last_data_dict.keys() & current_data_dict.keys():
if last_data_dict[country] != current_data_dict[country]:
for key in last_data_dict[country].keys() & current_data_dict[country].keys():
change = current_data_dict[country][key] - last_data_dict[country][key]
if change != 0:
result[country][key][f"last_{key}_value"] = last_data_dict[country][key]
result[country][key][f"updated_{key}_value"] = current_data_dict[country][key]
result[country][key]["change"] = change
print('Normal Defaultdict Output:')
print(result)
print('JSON Defaultdict Output:')
print(dumps(result, indent=4))
print('Non-Defaultdict Output:')
pprint(defaultdict_to_dict(result))
ZnJvbSBjb2xsZWN0aW9ucyBpbXBvcnQgZGVmYXVsdGRpY3QKZnJvbSBqc29uIGltcG9ydCBkdW1wcwpmcm9tIHBwcmludCBpbXBvcnQgcHByaW50CgpsYXN0X2RhdGEgPSBbeydjb3VudHJ5JzogJ1VTQScsICdjYXNlcyc6IDEwNDI1LCAnZGVhdGhzJzogMTcwNCwgJ3JlY292ZXJlZCc6IDI1MjUsICdhY3RpdmUnOiAxMDAwMjd9LAogICAgICAgICAgICB7J2NvdW50cnknOiAnQXVzdHJhbGlhJywgJ2Nhc2VzJzogMzA0NSwgJ2RlYXRocyc6IDE3MDQsICdyZWNvdmVyZWQnOiAyNTI1LCAnYWN0aXZlJzogMTAwMDI3fSwKICAgICAgICAgICAgeydjb3VudHJ5JzogJ0dlcm1hbnknLCAnY2FzZXMnOiA2MDI1LCAnZGVhdGhzJzogMTcwNCwgJ3JlY292ZXJlZCc6IDI1MjUsICdhY3RpdmUnOiAxMDAwMjd9XQoKY3VycmVudF9kYXRhID0gW3snY291bnRyeSc6ICdVU0EnLCAnY2FzZXMnOiAxMDQyNSwgJ2RlYXRocyc6IDE3MDQsICdyZWNvdmVyZWQnOiAyNTI1LCAnYWN0aXZlJzogMTAwMDI3fSwKICAgICAgICAgICAgICAgIHsnY291bnRyeSc6ICdBdXN0cmFsaWEnLCAnY2FzZXMnOiAzMDQ2LCAnZGVhdGhzJzogMTcwNCwgJ3JlY292ZXJlZCc6IDI1MjUsICdhY3RpdmUnOiAxMDAwMjh9LAogICAgICAgICAgICAgICAgeydjb3VudHJ5JzogJ0dlcm1hbnknLCAnY2FzZXMnOiA2MDI2LCAnZGVhdGhzJzogMTcwNiwgJ3JlY292ZXJlZCc6IDI1MjUsICdhY3RpdmUnOiAxMDAwMjZ9XQoKZGVmIGxpc3RfZGljdHNfdG9fbmVzdGVkX2RpY3Qoa2V5LCBsc3QpOgogICAgcmV0dXJuIHtkaWNba2V5XToge2s6IHYgZm9yIGssIHYgaW4gZGljLml0ZW1zKCkgaWYgayAhPSBrZXl9IGZvciBkaWMgaW4gbHN0fQoKZGVmIGRlZmF1bHRkaWN0X3RvX2RpY3QoZGYpOgogICAgcmVzdWx0ID0ge30KICAgIGZvciBrLCB2IGluIGRmLml0ZW1zKCk6CiAgICAgICAgaWYgaXNpbnN0YW5jZSh2LCBkZWZhdWx0ZGljdCk6CiAgICAgICAgICAgIHJlc3VsdFtrXSA9IGRpY3QodikKICAgICAgICAgICAgZGVmYXVsdGRpY3RfdG9fZGljdCh2KQogICAgcmV0dXJuIGRpY3QocmVzdWx0KQoKCmxhc3RfZGF0YV9kaWN0ID0gbGlzdF9kaWN0c190b19uZXN0ZWRfZGljdCgnY291bnRyeScsIGxhc3RfZGF0YSkKY3VycmVudF9kYXRhX2RpY3QgPSBsaXN0X2RpY3RzX3RvX25lc3RlZF9kaWN0KCdjb3VudHJ5JywgY3VycmVudF9kYXRhKQoKcmVzdWx0ID0gZGVmYXVsdGRpY3QobGFtYmRhOiBkZWZhdWx0ZGljdChkaWN0KSkKZm9yIGNvdW50cnkgaW4gbGFzdF9kYXRhX2RpY3Qua2V5cygpICYgY3VycmVudF9kYXRhX2RpY3Qua2V5cygpOgogICAgaWYgbGFzdF9kYXRhX2RpY3RbY291bnRyeV0gIT0gY3VycmVudF9kYXRhX2RpY3RbY291bnRyeV06CiAgICAgICAgZm9yIGtleSBpbiBsYXN0X2RhdGFfZGljdFtjb3VudHJ5XS5rZXlzKCkgJiBjdXJyZW50X2RhdGFfZGljdFtjb3VudHJ5XS5rZXlzKCk6CiAgICAgICAgICAgIGNoYW5nZSA9IGN1cnJlbnRfZGF0YV9kaWN0W2NvdW50cnldW2tleV0gLSBsYXN0X2RhdGFfZGljdFtjb3VudHJ5XVtrZXldCiAgICAgICAgICAgIGlmIGNoYW5nZSAhPSAwOgogICAgICAgICAgICAgICAgcmVzdWx0W2NvdW50cnldW2tleV1bZiJsYXN0X3trZXl9X3ZhbHVlIl0gPSBsYXN0X2RhdGFfZGljdFtjb3VudHJ5XVtrZXldCiAgICAgICAgICAgICAgICByZXN1bHRbY291bnRyeV1ba2V5XVtmInVwZGF0ZWRfe2tleX1fdmFsdWUiXSA9IGN1cnJlbnRfZGF0YV9kaWN0W2NvdW50cnldW2tleV0KICAgICAgICAgICAgICAgIHJlc3VsdFtjb3VudHJ5XVtrZXldWyJjaGFuZ2UiXSA9IGNoYW5nZQoKcHJpbnQoJ05vcm1hbCBEZWZhdWx0ZGljdCBPdXRwdXQ6JykKcHJpbnQocmVzdWx0KQoKcHJpbnQoJ0pTT04gRGVmYXVsdGRpY3QgT3V0cHV0OicpCnByaW50KGR1bXBzKHJlc3VsdCwgaW5kZW50PTQpKQoKcHJpbnQoJ05vbi1EZWZhdWx0ZGljdCBPdXRwdXQ6JykKcHByaW50KGRlZmF1bHRkaWN0X3RvX2RpY3QocmVzdWx0KSk=
Normal Defaultdict Output:
defaultdict(<function <lambda> at 0x2ac7d94b58c8>, {'Australia': defaultdict(<class 'dict'>, {'cases': {'last_cases_value': 3045, 'updated_cases_value': 3046, 'change': 1}, 'active': {'last_active_value': 100027, 'updated_active_value': 100028, 'change': 1}}), 'Germany': defaultdict(<class 'dict'>, {'cases': {'last_cases_value': 6025, 'updated_cases_value': 6026, 'change': 1}, 'active': {'last_active_value': 100027, 'updated_active_value': 100026, 'change': -1}, 'deaths': {'last_deaths_value': 1704, 'updated_deaths_value': 1706, 'change': 2}})})
JSON Defaultdict Output:
{
"Australia": {
"cases": {
"last_cases_value": 3045,
"updated_cases_value": 3046,
"change": 1
},
"active": {
"last_active_value": 100027,
"updated_active_value": 100028,
"change": 1
}
},
"Germany": {
"cases": {
"last_cases_value": 6025,
"updated_cases_value": 6026,
"change": 1
},
"active": {
"last_active_value": 100027,
"updated_active_value": 100026,
"change": -1
},
"deaths": {
"last_deaths_value": 1704,
"updated_deaths_value": 1706,
"change": 2
}
}
}
Non-Defaultdict Output:
{'Australia': {'active': {'change': 1,
'last_active_value': 100027,
'updated_active_value': 100028},
'cases': {'change': 1,
'last_cases_value': 3045,
'updated_cases_value': 3046}},
'Germany': {'active': {'change': -1,
'last_active_value': 100027,
'updated_active_value': 100026},
'cases': {'change': 1,
'last_cases_value': 6025,
'updated_cases_value': 6026},
'deaths': {'change': 2,
'last_deaths_value': 1704,
'updated_deaths_value': 1706}}}