【问题标题】:Merging a list of dictionaries in python based on one key/value pair?python - 基于一个键/值对合并python中的字典列表?
【发布时间】:2014-04-02 04:54:10
【问题描述】:

我在 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}]

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

换句话说,我想遍历这两个列表并获取每个列表项的“颜色”、“形状”和“优先级”的字典,其中“优先级”的值对于每个列表项的值都是最高的'形状')

我断断续续地在 SO 上搜索和尝试不同的东西几天,我终于屈服于询问。我尝试了各种版本的 max、key、lambda 等,但我在这里能找到的所有线程似乎都不是我想要的。

提前致谢!

【问题讨论】:

  • 列表是如何合并的?

标签: python dictionary python-2.6


【解决方案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'}]

由于这是具有唯一键的字典,给定形状的最后一项将替换具有相同形状的早期项。由于项目是按优先级排序的,所以 res 字典中的 {'shape': 'square', 'color': 'red', 'priority': 2}{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()

【讨论】:

    【解决方案2】:

    这是一个计划。它假设您不关心 dicts 顺序,但您可以修改它以关心。

    让我们看看我们有什么。首先,结果字典来自哪个列表并不重要,因此我们可以将它们链接起来。其次,从每组具有相同形状的字典中,我们准确地选择一个。看起来我们需要按形状对所有字典进行分组,然后为每个组选择一个优先级最高的字典。

    显而易见的方法是与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]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-28
      • 1970-01-01
      • 2016-02-20
      • 2016-04-07
      • 2022-11-14
      • 1970-01-01
      相关资源
      最近更新 更多