Python:如何根据对象的ID查找两个列表之间的交集?

时间:2019-02-07 01:08:02

标签: python

我知道如果我有两个整数列表,我可以简单地list(set(list1) & set(list2))来得到交集。但是,在我的两个列表中,我有可变的对象,即Node。 Node是可以使用值初始化的类。

无需执行双重for循环,是否有任何方法可以根据其ID获得两个列表的交集?我正在寻找类似于list(set(list1) & set(list2))的东西。

更新:通过id,我指的是Python中内置的id()函数,该函数返回对象在内存中存储的地址。

所以,我要问[Node1, Node2, Node3][Node100, Node2, Node3]的交集是什么。显然,我不能使用上面的设置交集方法。我需要通过访问内存来确定它们是相同的。如果我无法根据它们的value属性来识别它们,因为它们可能与Node1的值相同,但Node1可能具有与Node100相同的值,但是它们在内存中不是相同的对象。

2 个答案:

答案 0 :(得分:3)

不需要相交两个集合。在这种情况下,您只需检查id()是否在另一个集合中即可。

set2 = {id(n) for n in list2}
result = [n for n in list1 if id(n) in set2]

此代码的复杂度为O(n1 + n2)。我将通过以下等效但可读性更高的代码对此进行解释:

set2 = {id(n) for n in list2}  # O(n2)
result = []
for n in list1:  # O(n1)
    if id(n) in set2:  # O(1)
        result.append(n)  # O(1)

总共是O(n1 + n2)


如果仅通过定义__hash____eq__方法就可以对Node类进行更改,则还有另一种解决方案。

class Node:
    ...

    def __hash__(self):
        return id(self)

    def __eq__(self, another):
        return id(self) == id(another)


list1 = [...]
list2 = [...]

result = set(list1) & set(list2)

答案 1 :(得分:0)

您建议的解决方案将起作用。

class Node:
    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return "Node {}".format(self.value)

nodes1 = [Node(1), Node(2), Node(3)]
nodes2 = nodes1[:2] + [Node(4)]

common_nodes = set(nodes1) & set(nodes2)

print(common_nodes) # {Node 2, Node 1}

之所以可行,是因为尽管它是可变的,但默认情况下,您尚未为其定义__hash____eq__的类的实例将被其id进行散列和比较,因为它从object继承了这些方法。

您可以通过以下实验确认这是真的。

>>> obj = object()
>>> hash(obj)
155115580943
>>> id(obj)
2481849295088
>>> id(obj) // 16 == hash(obj)
True