根据一个键值对合并Python中的字典列表?

1 投票
2 回答
1097 浏览
提问于 2025-04-18 00:57

我在使用Python 2.6时,有两个字典列表,我想根据一个键的最高值来合并它们,这个键对应另一个键。列表大致是这样的:

[{shape: square, color: red, priority: 2},
{shape: circle, color: blue, priority: 2},
{shape: triangle, color: green, priority: 2}]

[{shape: square, color: green, priority: 3},
{shape: circle, color: red, priority: 1}]

我想得到的结果是这样的:

[{shape: square, color: green, priority: 3},
{shape: circle, color: blue, priority: 2},
{shape: triangle, color: green, priority: 2}]

(项目的顺序并不重要。)

换句话说,我想遍历这两个列表,获取每个列表项的'color'(颜色)、'shape'(形状)和'priority'(优先级)的字典,其中'priority'的值在每个'shape'的值中是最高的。

我在Stack Overflow上搜索并尝试了几天不同的方法,最终决定来问一下。我尝试了各种版本的max、key、lambda等,但我找到的所有讨论似乎都不是我想要的。

提前谢谢你们!

2 个回答

1

这里有一个计划。这个计划假设你不在乎字典的顺序,但你可以根据需要进行调整。

我们先看看现有的内容。首先,结果字典来自哪个列表并不重要,所以我们可以把它们串联起来。其次,对于每一组形状相同的字典,我们只选择一个。看起来我们需要先把所有字典按形状分组,然后为每组选择一个优先级最高的字典。

最简单的方法是使用 collections.defaultdict 来分组,然后在列表推导式中用 max 来选择每组中最好的字典。稍微复杂一点的方法是先按形状和优先级进行排序,然后用 itertools.groupby 按形状分组,再从每组中选择第一个元素:

from itertools import chain, groupby 

sorted_dicts = sorted(chain(list1, list2), 
                      key=lambda d: (d['shape'], -d['priority'])) 
groups = groupby(sorted_dicts, key=lambda d: d['shape'])
merged = [next(g) for _, g in groups]
1

只需使用一个新的字典,将合并后的列表按优先级排序,然后把每个字典放在这个合并后的列表里:

li1=[{'shape': 'square', 'color': 'red', 'priority': 2},
{'shape': 'circle', 'color': 'blue', 'priority': 2},
{'shape': 'triangle', 'color': 'green', 'priority': 2}]

li2=[{'shape': 'square', 'color': 'green', 'priority': 3},
{'shape': 'circle', 'color': 'red', 'priority': 1}]

res={}
for di in sorted(li1+li2, key=lambda d: d['priority']):
    res[di['shape']]=di

print res.values()  

输出结果是:

[{'color': 'blue', 'priority': 2, 'shape': 'circle'}, 
 {'color': 'green', 'priority': 3, 'shape': 'square'}, 
 {'color': 'green', 'priority': 2, 'shape': 'triangle'}]

因为这是一个键唯一的字典,所以同一种形状的最后一个项目会替换掉之前的同种形状的项目。由于这些项目是按优先级排序的,{'shape': 'square', 'color': 'red', 'priority': 2}res 字典中会被 {shape: square, color: green, priority: 3} 替换掉,因为 3 大于 2,依此类推。

所以在 Python 2.7 及以上版本中,你可以用一行代码完成这一切:

{di['shape']:di for di in sorted(li1+li2, key=lambda d: d['priority'])}.values()

撰写回答