我有2个字典,如下所示
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}]
我正在尝试通过比较这2个来实现以下目标
expected_output = [{'Australia':{'last_cases_value': 3045,'updated_cases_value':3046,'change':1,
{'last_active_value':100027,'updated_active_value':10028,'change':1}
{'Germany':{'last_cases_value': 6025,'updated_cases_value':6026,'change':1},
{'last_death_value':1704,'updated_death_value':1706,'change':2},
{'last_active_value':100027,'updated_active_value':10026,'change':-1}]
我尝试了很多事情,但是让我有点亲近的是
pairs = zip(last_data, current_data)
print([(x, y) for x, y in pairs if x != y])
以上代码的输出如下
[({'country': 'Australia', 'cases': 3045, 'deaths': 1704, 'recovered': 2525, 'active': 100027}, {'country': 'Australia', 'cases': 3046, 'deaths': 1704, 'recovered': 2525, 'active': 100028}), ({'country': 'Germany', 'cases': 6025, 'deaths': 1704, 'recovered': 2525, 'active': 100027}, {'country': 'Germany', 'cases': 6026, 'deaths': 1704, 'recovered': 2525, 'active': 100027})]
仍然无法弄清楚如何转换为我的预期输出
我正在使用最新版本的python3.8
任何帮助将不胜感激
答案 0 :(得分:2)
您的预期输出是无效有效。我可能会改用这样的嵌套字典:
{
"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
}
},
"Australia": {
"cases": {
"last_cases_value": 3045,
"updated_cases_value": 3046,
"change": 1
},
"active": {
"last_active_value": 100027,
"updated_active_value": 100028,
"change": 1
}
}
}
要达到上述目的,我首先将您的词典列表转换为以'country'
为键的嵌套词典:
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}
last_data_dict = list_dicts_to_nested_dict('country', last_data)
# {'USA': {'cases': 10425, 'deaths': 1704, 'recovered': 2525, 'active': 100027}, 'Australia': {'cases': 3045, 'deaths': 1704, 'recovered': 2525, 'active': 100027}, 'Germany': {'cases': 6025, 'deaths': 1704, 'recovered': 2525, 'active': 100027}}
current_data_dict = list_dicts_to_nested_dict('country', current_data)
# {'USA': {'cases': 10425, 'deaths': 1704, 'recovered': 2525, 'active': 100027}, 'Australia': {'cases': 3046, 'deaths': 1704, 'recovered': 2525, 'active': 100028}, 'Germany': {'cases': 6026, 'deaths': 1706, 'recovered': 2525, 'active': 100026}}
这也是一个好主意,因为从扫描整个词典中搜索特定国家/地区的数据将是 O(1),而不是 O(N)。这也使将来与这些国家相交变得更加容易,我将在下面显示。
然后将更改的数据添加到dict
的嵌套的二次深度 collections.defaultdict
中,因为它可以为您初始化新密钥。您可以查看此Nested defaultdict of defaultdict答案,以了解更多信息和其他方式。
result = defaultdict(lambda: defaultdict(dict))
# Get the intersecting keys.
# Avoids Key Errors in the future, if both dictionaries don't have the same key
for country in last_data_dict.keys() & current_data_dict.keys():
# Only deal with dictionaries that have changed
if last_data_dict[country] != current_data_dict[country]:
# Get intersecting keys between both dictionaries
for key in last_data_dict[country].keys() & current_data_dict[country].keys():
# Calculate the change between updated and previous data
change = current_data_dict[country][key] - last_data_dict[country][key]
# We only care about data that has changed
# Insert data into dictionary
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
然后,您可以使用json.dumps
将上述数据序列化并输出为JSON格式的字符串,因为以这种方式更容易输出嵌套的defaultdict
而不是将整个数据结构转换为{{1}递归或其他方法。 dict
仍然是defaultdict
的子类,因此可以将其视为普通词典。
dict
另外,如果您不关心输出,那么直接打印print(dumps(result, indent=4))
也是一个简单的选择:
defaultdict
作为一个额外的可选步骤,但又不需要 步骤,如上所述,我们可以创建一个递归函数,将嵌套的print(result)
# defaultdict(<function <lambda> at 0x000002355BC3AA60>, {'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'>, {'deaths': {'last_deaths_value': 1704, 'updated_deaths_value': 1706, 'change': 2}, 'cases': {'last_cases_value': 6025, 'updated_cases_value': 6026, 'change': 1}, 'active': {'last_active_value': 100027, 'updated_active_value': 100026, 'change': -1}})})
转换为子类型为{{1 }}:
defaultdict
可按预期工作:
dict
您可以查看ideone.com上的完整实现。
答案 1 :(得分:2)
您可以使用列表和字典理解:
l = {l['country']: {'v': l['cases'], 'a': l['active']} for l in last_data}
c = {l['country']: {'v': l['cases'], 'a': l['active']} for l in current_data}
result = [{k: [{'last_cases_value': l[k]['v'],
'updated_cases_value': c[k]['v'],
'change': c[k]['v'] - l[k]['v']},
{'last_active_value': l[k]['a'],
'updated_active_value': c[k]['a'],
'change': c[k]['a'] - l[k]['a']}]} for k in c.keys()]
输出:
[{'USA': [{'last_cases_value': 10425,
'updated_cases_value': 10425,
'change': 0},
{'last_active_value': 100027,
'updated_active_value': 100027,
'change': 0}]},
{'Australia': [{'last_cases_value': 3045,
'updated_cases_value': 3046,
'change': 1},
{'last_active_value': 100027,
'updated_active_value': 100028,
'change': 1}]},
{'Germany': [{'last_cases_value': 6025,
'updated_cases_value': 6026,
'change': 1},
{'last_active_value': 100027,
'updated_active_value': 100026,
'change': -1}]}]
如果您只想保留结果已更改的国家/地区,则保留结果:
result = [{k: [{'last_cases_value': l[k]['v'],
'updated_cases_value': c[k]['v'],
'change': c[k]['v'] - l[k]['v']},
{'last_active_value': l[k]['a'],
'updated_active_value': c[k]['a'],
'change': c[k]['a'] - l[k]['a']}]}
for k in c.keys() if c[k]['a'] - l[k]['a'] and c[k]['v'] - l[k]['v']]
输出:
[{'Australia': [{'last_cases_value': 3045,
'updated_cases_value': 3046,
'change': 1},
{'last_active_value': 100027,
'updated_active_value': 100028,
'change': 1}]},
{'Germany': [{'last_cases_value': 6025,
'updated_cases_value': 6026,
'change': 1},
{'last_active_value': 100027,
'updated_active_value': 100026,
'change': -1}]}]
答案 2 :(得分:0)
您可以使用pandas
:
import pandas as pd
curr_df=pd.DataFrame(current_data)
last_df=pd.DataFrame(last_data)
df=curr_df.merge(last_df, on="country", suffixes=["_updated", "_last"])
res=df[sorted(df.columns)].rename(columns={c: "_".join(c.split("_")[::-1])+"_value" for c in df.columns if c!="country"}).set_index('country').to_dict('index')
res=[dict([(k, [dict(p) for p in list(zip(v.items(), list(v.items())[1:]))[::2]])]) for k, v in res.items()]
输出:
[{'USA': [{'last_active_value': 100027, 'updated_active_value': 100027}, {'last_cases_value': 10425, 'updated_cases_value': 10425}, {'last_deaths_value': 1704, 'updated_deaths_value': 1704}, {'last_recovered_value': 2525, 'updated_recovered_value': 2525}]}, {'Australia': [{'last_active_value': 100027, 'updated_active_value': 100028}, {'last_cases_value': 3045, 'updated_cases_value': 3046}, {'last_deaths_value': 1704, 'updated_deaths_value': 1704}, {'last_recovered_value': 2525, 'updated_recovered_value': 2525}]}, {'Germany': [{'last_active_value': 100027, 'updated_active_value': 100026}, {'last_cases_value': 6025, 'updated_cases_value': 6026}, {'last_deaths_value': 1704, 'updated_deaths_value': 1706}, {'last_recovered_value': 2525, 'updated_recovered_value': 2525}]}]
注意-默认情况下,merge
进行内部联接,如果要完整的外部/左侧外部,请查看其how
参数:
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.merge.html
zip
公式-用于成对地整形列表-取自此处:https://stackoverflow.com/a/5394908/11610186