查找两个列表中不存在的对象的最佳方法

Kar*_*tik 4 python sorting data-structures

我正在研究一个模块,该模块依赖于检查2个列表中是否存在任何对象.该实现应该是在Python中.

考虑简化的对象def:

class Foo(object):

  def __init__(self, attr_one=None, attr_two=None):
    self.attr_one = attr_one
    self.attr_two = attr_two

  def __eq__(self, other):
    return self.attr_one == other.attr_one and self.attr_two == other.attr_two
Run Code Online (Sandbox Code Playgroud)

我有两个单独的列表,可以封装类Foo的多个实例,如下所示:

list1 = [Foo('abc', 2), Foo('bcd', 3), Foo('cde', 4)]
list2 = [Foo('abc', 2), Foo('bcd', 4), Foo('efg', 5)]
Run Code Online (Sandbox Code Playgroud)

我需要弄清楚一个列表中存在的对象,而另一个列表中的对象基于attr_one.在这种情况下,下面给出了第一个列表中存在的项目和第二个列表中缺失的项目的期望输出.

`['Foo('bcd', 3), Foo('cde', 4)]` 
Run Code Online (Sandbox Code Playgroud)

同样,列表2中的项目也不在列表1中

 [Foo('bcd', 4), Foo('efg', 5)]
Run Code Online (Sandbox Code Playgroud)

我想知道是否有办法匹配attr_one的基础.

  List 1                 List 2        
  Foo('bcd', 3)          Foo('bcd', 4)
  Foo('cde', 4)          None
  None                   Foo('efg', 5)
Run Code Online (Sandbox Code Playgroud)

小智 8

由于您已经__eq__定义了一个方法,因此您可以使用列表推导来查找任一列表中对象的唯一性.

print [obj for obj in list1 if obj not in list2]
Run Code Online (Sandbox Code Playgroud)


Kyl*_*and 4

快速比较列表以确定哪些元素存在于一个列表中而不是另一个列表中的一种好方法是从原始列表创建集合并获取两个集合之间的差异。为了使列表成为一个集合,它包含的对象必须是hashable,因此您必须__hash__()Foo对象定义一个新方法:

def __hash__(self):
    return hash((self.attr_one,self.attr_two))
Run Code Online (Sandbox Code Playgroud)

请注意,由于元组是可哈希的,只要 和attr_oneattr_two可哈希类型,这个实现应该非常可靠。

现在,要确定哪些元素存在于一个列表中而不是另一个列表中:

set1 = set(list1)
set2 = set(list2)
missing_from_1 = set2 - set1
missing_from_2 = set1 - set2
Run Code Online (Sandbox Code Playgroud)

要仅基于其中一个属性来执行此操作,您可以仅使用属性本身来创建集合:

set1 = set([i.attr_one for i in list1])
Run Code Online (Sandbox Code Playgroud)

当然,这意味着您最终得到的结果只会告诉您attr_one一个列表中存在的值,而不是另一个列表中存在的值,而不是为您提供实际的Foo对象。然而,一旦你有了“丢失”的集合,这些对象本身就很容易找到:

missing_Foos = set()
for attr in missing_from_2:
    for i in list1:
        if i.attr_one == attr:
            missing_Foos.add(i)
Run Code Online (Sandbox Code Playgroud)

但是,如果列表很长,这在计算上可能会相当昂贵。

编辑:只有当您有非常大的列表并因此需要利用集合运算的计算效率时,使用集合才真正有用。否则,按照其他答案中的建议,简单地使用列表理解可能会更简单。