Python 3.x 将字典列表与公共键合并,而不合并值
我有多个字典列表,如下所示:Python 3.x 将字典列表与公共键合并,而不合并值,python-3.x,Python 3.x,我有多个字典列表,如下所示: data_aus = [{'name': '2018,7', 'aus_ct': 13}, {'name': '2018,8', 'aus_ct': 3}, {'name': '2018,9', 'aus_ct': 3}] data_asia = [{'name': '2018,7', 'asia_ct': 10}, {'name': '2018,8', 'asia_ct': 11}, {'name': '2018,9', 'asia_ct': 6}] dat
data_aus =
[{'name': '2018,7', 'aus_ct': 13}, {'name': '2018,8', 'aus_ct': 3}, {'name': '2018,9', 'aus_ct': 3}]
data_asia =
[{'name': '2018,7', 'asia_ct': 10}, {'name': '2018,8', 'asia_ct': 11}, {'name': '2018,9', 'asia_ct': 6}]
data_us =
[{'name': '2018,7', 'us_ct': 5}, {'name': '2018,8', 'us_ct': 8}, {'name': '2018,9', 'us_ct': 9}, {'name': '2018,10', 'us_ct': 23}]
data_uk =
[{'name': '2018,7', 'uk_ct': 15}, {'name': '2018,8', 'uk_ct': 7}, {'name': '2018,9', 'uk_ct': 13}]
我想根据一个名为name
的公用键,将这些列表合并成一个字典列表
结果应该如下所示:
data_combined = [
{'name': '2018,7', 'aus_ct': 13, 'asia_ct': 10, 'us_ct': 5, 'uk_ct':15},
{'name': '2018,8', 'aus_ct': 3, 'asia_ct': 11, 'us_ct': 8, 'uk_ct':7},
...]
有没有一个简单的方法可以做到这一点?请帮助。1)将所有数据准备到一个列表中,并在数据中查找所有可用月份
# Put all data into a single list
all_data = [month_data for country_data in [data_aus, data_asia, data_us, data_uk] for month_data in country_data]
# Figure out the months available
months = set(map(lambda entry: entry['name'], all_data))
2) 通过逐月迭代并通过字典将数据合并
data_combined = []
# Iterate month by month
for month in months:
# Get all the data from a single month (list of dicts)
month_data = filter(lambda entry: entry['name'] == month, all_data)
# "Tricky part" merge the list of dictionaries
sigle_month_data = {k: v for d in month_data for k, v in d.items()}
# Append to the overall combined list
data_combined.append(single_month_data)
3) 结果
尝试#1
编辑:如果键的顺序不同,则编辑失败
通过创建一个函数来合并任意数量的词典,实现了此解决方案:
from itertools import zip_longest
def merge_dicts(dicts):
result = []
for d in dicts:
result = [{**u, **v} for u, v in zip_longest(result, d, fillvalue={})]
return result
并将所有列表作为输入传递:
merge_dicts([data_aus, data_asia, data_us, data_uk])
输出为:
[
{
"name": "2018,8",
"aus_ct": 5,
"asia_ct": 5,
"us_ct": 8,
"uk_ct": 9
},
{
"name": "2018,9",
"aus_ct": 2,
"asia_ct": 1,
"us_ct": 2,
"uk_ct": 6
},
{
"name": "2018,10",
"aus_ct": 3,
"asia_ct": 1,
"us_ct": 3,
"uk_ct": 11
},
{
"name": "2018,11",
"aus_ct": 9,
"asia_ct": 1,
"us_ct": 1,
"uk_ct": 1
},
{
"name": "2019,6",
"aus_ct": 7,
"us_ct": 1,
"uk_ct": 2
},
{
"name": "2019,8",
"aus_ct": 7,
"uk_ct": 1
},
{
"name": "2019,1",
"aus_ct": 2
},
{
"name": "2019,3",
"aus_ct": 2
},
{
"name": "2019,4",
"aus_ct": 1
},
{
"name": "2019,5",
"aus_ct": 4
},
{
"name": "2019,6",
"aus_ct": 4
},
{
"name": "2019,7",
"aus_ct": 3
},
{
"name": "2019,8",
"aus_ct": 2
},
{
"name": "2019,9",
"aus_ct": 1
},
{
"name": "2019,10",
"aus_ct": 1
}
]
谢谢你的回复。让我知道在性能方面是否有更好的方法 尝试#2
我想这应该行得通:
import itertools
from collections import defaultdict
def merge_dicts(shared_key, *dicts):
# Remove empty dicts (if any)
dicts = list(filter(None, dicts))
# Merging dicts based on shared keys
result = defaultdict(dict)
for dictionary in itertools.chain.from_iterable(dicts):
result[dictionary[shared_key]].update(dictionary)
# And converting results from {key1: dict1, key2: dict2, ...} to list of dicts [dict1, dict2, ...]
return list(result.values())
打电话给
merge_dicts('name', data_aus, data_asia, data_us, data_uk)
如果这种方法有任何问题,请告诉我。您的代码在哪里?这些名称下列出的变量是
数据?
还是您给了每个变量一个名称?谢谢,但我找到了一种更简单的方法。@saran3h当然,没问题。我想这将取决于你对“更简单”的定义。)两种解决方案都有7行代码…:要使您的输出具有代表性和意义,它应该与您的初始输入相关联,但事实并非如此。现在看来,我不明白你的意思,但这正是我想要的。如果你指的是与我在这个问题中不匹配的值,当然它们不是实际数据的代表,而是用来传达意义的。这种方法根本不考虑你的条件“基于一个叫做“代码>名字<代码>的共同密钥”。如果任何dict中项目的顺序发生变化,以及dict(条目)中键的顺序不同,则不会产生正确的结果。这不是解决方案,所以,看看你原来的问题,你已经得到了预期的结果:{name':'2018,8','aus_-ct':3,'asia_-ct':11,'us_-ct':8,'uk_-ct':7}
,但在你的回答中你有{“name:'2018,8”,“aus_-ct:'5,'asia_-ct':5,'us_-ct':8,'uk u-ct':9}
。确保你得到了正确的结果…@bruno正如我上面所说的,这些值是任意表达意思的。
merge_dicts('name', data_aus, data_asia, data_us, data_uk)