【问题标题】:How to find the difference between two lists of dictionaries?如何找到两个字典列表之间的区别?
【发布时间】:2014-10-22 13:29:25
【问题描述】:

我有两个字典列表,我想找出它们之间的区别(即第一个列表中存在但第二个列表中不存在的内容,以及第二个列表中存在但第一个列表中不存在的内容)。

问题在于它是一个字典列表

a = [{'a': '1'}, {'c': '2'}]
b = [{'a': '1'}, {'b': '2'}]

set(a) - set(b)

结果

TypeError: unhashable type: 'dict'

期望的结果:

{'c': '2'}

我该如何做到这一点?

【问题讨论】:

  • 你的字典真的只有单项吗?如果是这样,将列表变成一个字典不是更有意义吗?
  • 不,它们是多个项目(最有可能每个大约 15 个),这将是每个列表中大约 3000 到 1000 个字典的列表
  • 你能检查一下你想要的结果吗?根据您的定义,您正在寻找 symmetric difference

标签: python list dictionary set


【解决方案1】:

可以使用in操作符查看是否在列表中

a = [{'a': '1'}, {'c': '2'}]
b = [{'a': '1'}, {'b': '2'}]

>>> {'a':'1'} in a
True
>>> {'a':'1'} in b
True

>>> [i for i in a if i not in b]
[{'c': '2'}]

【讨论】:

    【解决方案2】:

    我想找出它们之间的区别(即存在于第一个列表中但不存在于第二个列表中的内容,以及存在于第二个列表中但不存在于第一个列表中的内容

    根据你的定义,你找的是Symmetric difference

    >>> import itertools
    
    >>> a = [{'a': '1'}, {'c': '2'}]
    >>> b = [{'a': '1'}, {'b': '2'}]
    >>> intersec = [item for item in a if item in b]
    >>> sym_diff = [item for item in itertools.chain(a,b) if item not in intersec]
    
    >>> intersec
    [{'a': '1'}]
    >>> sym_diff
    [{'c': '2'}, {'b': '2'}
    

    或者(使用您的示例中给出的plain difference):

    >>> a_minus_b = [item for item in a if item not in b]
    >>> b_minus_a = [item for item in b if item not in a]
    >>> sym_diff = list(itertools.chain(a_minus_b,b_minus_a))
    
    >>> a_minus_b
    [{'c': '2'}]
    >>> b_minus_a
    [{'b': '2'}]
    >>> sym_diff
    [{'c': '2'}, {'b': '2'}]
    

    【讨论】:

    • 这在其中一个答案中被引用,但我相信这正是 OP 在这里想要的......所以 +1。一个问题,你能不能只使用+ 运算符将a_minis_bb_minus_a 连接成sym_diff 而不是使用itertools.chain
    • @KhalilAmmour-خليلعمور 是的,你可以。但是使用itertools.chain(),您不必在使用它之前在内存中构建结果列表。对于“大”列表尤其重要。不过,为了更加一致,我应该在这里使用生成器而不是列表推导:a_minus_b = (item for item in a if item not in b)。但这在示例代码中会更加棘手,因为生成器会在您使用项目时消耗它们。
    • 啊哈……我明白了……那是为了优化内存,你能给我看一个生成器的例子吗,如果你愿意的话,可以通过编辑你的答案吗?
    【解决方案3】:

    你也可以用filterlambda

    如果您想要每个列表中的不同项目:

    print filter(lambda x: x not in b,a) + filter(lambda x: x not in a,b)
    
    [{'c': '2'}, {'b': '2'}]
    

    或者只是filter(lambda x: x not in b,a) 来获取a 中的元素,而不是b 中的元素 如果你不想在内存中创建完整的字典列表,你可以使用itertools.ifilter

    from itertools import ifilter
    
    diff = ifilter(lambda x: x not in b,a)
    

    然后只遍历 diff:

    for uniq in diff:
       print uniq
    

    【讨论】:

      猜你喜欢
      • 2016-08-16
      • 2014-11-04
      • 2012-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-25
      • 2011-09-06
      • 1970-01-01
      相关资源
      最近更新 更多