当两个列表的长度不同时(使用Python 3.6),我想在一个键上合并两个字典列表。例如,如果我们有一个名为l1
的词典列表:
l1 = [{'pcd_sector': 'ABDC', 'coverage_2014': '100'},
{'pcd_sector': 'DEFG', 'coverage_2014': '0'}]
另一个名为l2
的词典列表:
l2 = [{'pcd_sector': 'ABDC', 'asset': '3G', 'asset_id': '2gs'},
{'pcd_sector': 'ABDC', 'asset': '4G', 'asset_id': '7jd'},
{'pcd_sector': 'DEFG', 'asset': '3G', 'asset_id': '3je'},
{'pcd_sector': 'DEFG', 'asset': '4G', 'asset_id': '8js'},
{'pcd_sector': 'CDEF', 'asset': '3G', 'asset_id': '4jd'}]
如何使用pcd_sector
合并它们以获得此(?):
result = [{'pcd_sector': 'ABDC', 'asset': '3G', 'asset_id': '2gs', 'coverage_2014': '100'},
{'pcd_sector': 'ABDC', 'asset': '4G', 'asset_id': '7jd', 'coverage_2014': '100'},
{'pcd_sector': 'DEFG', 'asset': '3G', 'asset_id': '3je', 'coverage_2014': '0'},
{'pcd_sector': 'DEFG', 'asset': '4G', 'asset_id': '8js', 'coverage_2014': '0'},
{'pcd_sector': 'CDEF', 'asset': '3G', 'asset_id': '4jd'}]
到目前为止我尝试了什么
我已经使用以下代码合并了两个列表,但遗憾的是我最终得到了一个简短的版本,而不是所需的完整数据结构。
import pprint
grouped = {}
for d in l1 + l2:
grouped.setdefault(d['pcd_sector'], {'asset':0, 'asset_id':0, 'coverage_2014':0}).update(d)
result = [d for d in grouped.values()]
pprint.pprint(result)
因此,当我运行代码时,我最终得到了这个简短的输出:
result = [{'pcd_sector': 'ABDC', 'asset': '3G', 'asset_id': '2gs', 'coverage_2014': '100'},
{'pcd_sector': 'DEFG', 'asset': '4G', 'asset_id': '8js', 'coverage_2014': '0'},
{'pcd_sector': 'CDEF', 'asset': '3G', 'asset_id': '4jd'}]
答案 0 :(得分:2)
您的方法存在的问题是,您的数据被放入grouped
字典中,'pcd_sector'
作为键,但您的l2
有多个dicts具有相同的'pcd_sector'
。您可以使用'pcd_sector', 'asset'
元组作为l2
的键,但它不再适用于l1
。因此,您需要分两步进行处理,而不是直接在l1 + l2
上进行迭代。
如果pcd_sector
中的l1
个密钥是唯一的,您可以创建一个大字典而不是小字典列表:
>>> d1 = {d['pcd_sector']:d for d in l1}
>>> d1
{'ABDC': {'pcd_sector': 'ABDC', 'coverage_2014': '100'}, 'DEFG': {'pcd_sector': 'DEFG', 'coverage_2014': '0'}}
然后,您只需要合并具有相同pcd_sector
键的词组:
>>> [dict(d, **d1.get(d['pcd_sector'], {})) for d in l2]
[{'asset_id': '2gs', 'coverage_2014': '100', 'pcd_sector': 'ABDC', 'asset': '3G'}, {'asset_id': '7jd', 'coverage_2014': '100', 'pcd_sector': 'ABDC', 'asset': '4G'}, {'asset_id': '3je', 'coverage_2014': '0', 'pcd_sector': 'DEFG', 'asset': '3G'}, {'asset_id': '8js', 'coverage_2014': '0', 'pcd_sector': 'DEFG', 'asset': '4G'}, {'asset_id': '4jd', 'pcd_sector': 'CDEF', 'asset': '3G'}]
总而言之,代码变为:
l1 = [{'pcd_sector': 'ABDC', 'coverage_2014': '100'},
{'pcd_sector': 'DEFG', 'coverage_2014': '0'}]
l2 = [{'pcd_sector': 'ABDC', 'asset': '3G', 'asset_id': '2gs'},
{'pcd_sector': 'ABDC', 'asset': '4G', 'asset_id': '7jd'},
{'pcd_sector': 'DEFG', 'asset': '3G', 'asset_id': '3je'},
{'pcd_sector': 'DEFG', 'asset': '4G', 'asset_id': '8js'},
{'pcd_sector': 'CDEF', 'asset': '3G', 'asset_id': '4jd'}]
d1 = {d['pcd_sector']:d for d in l1}
result = [dict(d, **d1.get(d['pcd_sector'], {})) for d in l2]
import pprint
pprint.pprint(result)
# [{'asset': '3G',
# 'asset_id': '2gs',
# 'coverage_2014': '100',
# 'pcd_sector': 'ABDC'},
# {'asset': '4G',
# 'asset_id': '7jd',
# 'coverage_2014': '100',
# 'pcd_sector': 'ABDC'},
# {'asset': '3G',
# 'asset_id': '3je',
# 'coverage_2014': '0',
# 'pcd_sector': 'DEFG'},
# {'asset': '4G',
# 'asset_id': '8js',
# 'coverage_2014': '0',
# 'pcd_sector': 'DEFG'},
# {'asset': '3G', 'asset_id': '4jd', 'pcd_sector': 'CDEF'}]
答案 1 :(得分:1)
您可以根据pcd_sector
创建查找字典,并根据以下内容更新原始的字典列表:
>>> import copy
>>> lookup = { x['pcd_sector'] : x for x in l1 }
>>> result = copy.deepcopy(l2)
>>> for d in result:
... d.update(lookup.get(d['pcd_sector'], {})) # golfed courtesy Ashwini Chaudhary
...
>>> result
[{'pcd_sector': 'ABDC', 'asset': '3G', 'asset_id': '2gs', 'coverage_2014': '100'},
{'pcd_sector': 'ABDC', 'asset': '4G', 'asset_id': '7jd', 'coverage_2014': '100'},
{'pcd_sector': 'DEFG', 'asset': '3G', 'asset_id': '3je', 'coverage_2014': '0'},
{'pcd_sector': 'DEFG', 'asset': '4G', 'asset_id': '8js', 'coverage_2014': '0'},
{'pcd_sector': 'CDEF', 'asset': '3G', 'asset_id': '4jd'}]
答案 2 :(得分:0)
使用pandas
的解决方案:
import pandas as pd
df1 = pd.DataFrame(l1)
df2 = pd.DataFrame(l2)
dfr = df1.join(df2, how='outer')
print(dfr)
输出:
coverage_2014 pcd_sector asset asset_id
0 100 ABDC 3G 2gs
1 100 ABDC 4G 7jd
2 0 DEFG 3G 3je
3 0 DEFG 4G 8js
4 NaN CDEF 3G 4jd
如果您想再次将其作为字典:
result = dfr.to_dict('records')
print(result)
输出(添加了换行符):
[{'coverage_2014': '100', 'pcd_sector': 'ABDC', 'asset': '3G', 'asset_id': '2gs'},
{'coverage_2014': '100', 'pcd_sector': 'ABDC', 'asset': '4G', 'asset_id': '7jd'},
{'coverage_2014': '0', 'pcd_sector': 'DEFG', 'asset': '3G', 'asset_id': '3je'},
{'coverage_2014': '0', 'pcd_sector': 'DEFG', 'asset': '4G', 'asset_id': '8js'},
{'coverage_2014': nan, 'pcd_sector': 'CDEF', 'asset': '3G', 'asset_id': '4jd'}]