两个列表之间的Python差异

两个列表之间的Python差异,python,python-3.x,dictionary,Python,Python 3.x,Dictionary,我发现了很多例子,但没有一个有重复的项目 我有两份清单: d1 = [{"id": 1, "value": 2}, {"id": 1, "value": 2}] d2 = [{"id": 1, "value": 2}, {"id": 4, "value": 4}] 我想要实现的是: d1-d2 [{"id": 1,

我发现了很多例子,但没有一个有重复的项目

我有两份清单:

d1 = [{"id": 1, "value": 2}, {"id": 1, "value": 2}]
d2 = [{"id": 1, "value": 2}, {"id": 4, "value": 4}]
我想要实现的是:

d1-d2
[{"id": 1, "value": 2}]

d2-d1
[{"id": 4, "value": 4}]

diff(d1, d2)
[{"id": 1, "value": 2}, {"id": 4, "value": 4}]

不优雅,但这似乎有效:

def diff(d1, d2):
  found = []
  to_return = []
  for item in d1:
    if item in found:
      continue
    found += [item]
    to_return += [item] * (len(list(filter(lambda x : x == item, d1))) - len(list(filter(lambda x : x == item, d2))))
  return to_return

你可以做这样的事情,但它并不漂亮:

def sub(d1, d2):
    d2_ = d2.copy()
    res = []
    for elem in d1:
        if elem in d2_:
            d2_.remove(elem)
        else:
            res.append(elem)
    return res

然后,您可以使用
sub(d1,d2)+sub(d2,d1)
获得
diff(d1,d2)
假设您的值,而不仅仅是键,在每个字典中都是可散列的,您可以将每个
dict
s
.items()
,将它们收集到,并对
计数器
s执行类似异或的操作,以获得不同的计数。然后您只需再次展平
计数器
,并将
冻结集
s转换回
dict
s:

from collections import Counter

def diff(l1, l2):
    c1 = Counter(frozenset(d.items()) for d in l1)
    c2 = Counter(frozenset(d.items()) for d in l2)
    c1xc2 = (c1 - c2) + (c2 - c1)  # Equivalent to c1 ^ c2 if they were sets, but we need counts, and Counter doesn't support ^
    # elements() flattens the Counter to iterable of repeated values, map(dict, ...)
    # converts frozensets back to dicts
    return list(map(dict, c1xc2.elements()))
计算
d1-d2
d2-d1
的简单操作留作练习;在所有情况下,关键是将
目录的
列表
转换为
目录的
冻结集的
计数器
项()
,用
-
执行您关心的操作,然后转换回
目录的
列表


这应该是相当有效的(在组合输入大小上大致
O(n)
);改进它需要更多的自定义代码,这显然不值得费心。

这两个列表的结合不是你想要的吗?它看起来没有什么区别(即“第一个列表中的元素,而不是第二个列表中的元素”),至少对于函数“diff”,您的dict总是有相同的键吗?您可以将它们转换为元组,然后将它们放入集合中,并对它们使用所有的集合操作。通过减去d1-d2,我想得到需要删除的项目(它们在列表1中,但不在列表2中)。通过减去d2-d1,我想得到我需要添加的元素(它们在d2中,但不在d1中)。这里有一个优雅的解决方案,使用过滤器,但我不够聪明,发现它非常复杂,可能很难维护代码。是的,上面的答案更好;这里有一个一行的答案,但它并不真正值得找到。我将把它作为另一个例子,以防有人关注。这是一个很好的答案+1。请注意,使用这种方法也可以轻松定义
sub
函数。@Moosefeather:Yar。我把它留作练习(毕竟这只是
diff
函数的简化)。最好让OP编写,以确保他们首先理解
diff
;如果他们不这样做,他们可以在这里的评论中询问后续内容。@ShadowRanger它也应该与
tuple
一起工作,而不是
frozenset
@ChihebNexus:在现代Python中,插入顺序为
dict
s时,如果
dict
s都是以相同的顺序构造的,它就会工作。但是如果它们不是,例如,如果
d2
被定义为OP的问题中所示的,但是
d1
被定义为
d1=[{“值”:2,“id”:1},{“值”:2,“id”:1}]
id
之前定义,OP的反面),
元组将中断(由于排序)而
frozenset
将继续工作。我不想依靠插入顺序的一致性来保证正确性。它不会给你带来任何好处;对于
计数器
@ShadowRanger Good point,这些值仍然需要可散列。我忘了点菜会弄坏柜台。