两个或更多字典的交集

时间:2018-10-02 10:24:42

标签: python python-3.x

我有

l1 = [{"value": 1, "label": "One"}, {"value": 2, "label": "Two"}]
l2 = [{"value": 1, "label": "One"}, {"value": 2, "label": "Two"}]
l3 = [{"value": 1, "label": "One"}, {"value": 3, "label": "Three"}]
l4 = [{"value": 4, "label": "Four"}]

我需要这样的东西:

def foo(*lists):
    ...

返回:

foo(l1, l2) -> [{"value": 1, "label": "One"}, {"value": 2, "label": "Two"}] 
foo(l2, l3) -> [{"value": 1, "label": "One"}]
foo(l1, l2, l3) -> [{"value": 1, "label": "One"}]
foo(l1, l2, l3, l4) -> []

编辑(对不起,我删掉了部分问题): 输出列表中的顺序无关紧要。

我尝试使用这些集合,但是列表中的字典是不可散列的。 因此,我尝试了将Frozen dict或tuple中的dict转换,但是输入dict中的键顺序应该不重要:

{"value": 1, "label": "One"} == {"label": "One", "value": 1}

l5 = [{"value": 1, "label": "One"}]
l6 = [{"label": "One", "value": 1}]
foo(l5, l6) -> [{"value": 1, "label": "One"}]

非常感谢。

1 个答案:

答案 0 :(得分:0)

您可以将字典列表转换为字典项元组集合,以便可以使用functools.reduce对所有集合执行set.intersection,然后将结果集序列转换为列表通过将序列映射到dict构造函数实现

from functools import reduce
def intersection(*lists):
    return list(map(dict, reduce(set.intersection, ({tuple(d.items()) for d in l} for l in lists))))

这样在您的示例输入中:

print(intersection(l1, l2))
print(intersection(l2, l3))
print(intersection(l1, l2, l3))
print(intersection(l1, l2, l3, l4))

将输出:

[{'value': 1, 'label': 'One'}, {'value': 2, 'label': 'Two'}]
[{'value': 1, 'label': 'One'}]
[{'value': 1, 'label': 'One'}]
[]