简体   繁体   English

Python 两个列表之间的差异

[英]Python Difference between 2 lists

I found many examples but not one with duplicate items.我发现了很多例子,但没有一个有重复项目。

I have 2 list of dict:我有 2 个字典列表:

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

What I want to achieve is:我想要实现的是:

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

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

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

You can do something like this but it's not that pretty:你可以做这样的事情,但它不是那么漂亮:

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

Then you can use sub(d1, d2) + sub(d2, d1) to get diff(d1, d2) .然后你可以使用sub(d1, d2) + sub(d2, d1)来获得diff(d1, d2)

Assuming your values, not just the keys, in each dictionary are hashable, you can make frozenset s of each dict s .items() , collect them into a collections.Counter , and perform an xor-like operation on the Counter s to get the disparate counts.假设您的值,而不仅仅是键,在每个字典中都是可散列的,您可以制作每个dict s frozenset .items()的 frozenset ,将它们收集到collections.Counter中,并对Counter s 执行类似 xor 的操作以获得不同的计数。 Then you just flatten out the Counter again, and convert the frozenset s back to dict s:然后你只需再次展平Counter ,并将frozenset 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()))

The simpler operation of computing d1 - d2 or d2 - d1 is left as an exercise;计算d1 - d2d2 - d1的更简单操作留作练习; the key in all cases is converting your list of dict s to Counter s of frozenset s of the dict 's .items() , performing the operation you care about with - , then converting back to a list of dict s.在所有情况下,关键是将您的dict list转换为dict.items()frozensetCounter ,使用-执行您关心的操作,然后转换回dict list

This should be fairly efficient (roughly O(n) on combined input sizes);这应该是相当有效的(在组合输入大小上大约为O(n) ); improving on it would require a lot more custom code that's frankly not worth the bother.改进它需要更多的自定义代码,坦率地说,这不值得费心。

Not elegant, but this seems to work:不优雅,但这似乎有效:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM