根据一个键值对合并Python中的字典列表?
我在使用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 个回答
这里有一个计划。这个计划假设你不在乎字典的顺序,但你可以根据需要进行调整。
我们先看看现有的内容。首先,结果字典来自哪个列表并不重要,所以我们可以把它们串联起来。其次,对于每一组形状相同的字典,我们只选择一个。看起来我们需要先把所有字典按形状分组,然后为每组选择一个优先级最高的字典。
最简单的方法是使用 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]
只需使用一个新的字典,将合并后的列表按优先级排序,然后把每个字典放在这个合并后的列表里:
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()