Python检查对象是否在对象列表中

时间:2010-04-01 08:35:16

标签: python

我在Python中有一个对象列表。然后我有另一个对象列表。我想浏览第一个列表,看看是否有任何项目出现在第二个列表中。

我以为我可以做到

for item1 in list1:
    for item2 in list2:
        if item1 == item2:
            print "item %s in both lists"

然而,这似乎不起作用。虽然我这样做:

if item1.title == item2.title:

它运作正常。我有比这更多的属性,所以如果我不需要,不要真的想做一个比较所有属性的if if语句。

任何人都可以给我帮助或建议我可以做些什么来找到两个列表中出现的对象。

由于

7 个答案:

答案 0 :(得分:29)

假设您的对象只有一个与{1}}属性相关的属性,则必须按如下方式实现title方法:

__eq__

当然,如果您有更多与平等相关的属性,那么您也必须包含这些属性。您也可以考虑实施class YourObject: [...] def __eq__(self, other): return self.title == other.title __ne__以保持一致的行为。

答案 1 :(得分:9)

如果对象不是同一个实例,则需要为python实现__eq__方法,以便能够判断2个对象实际上是否相等。

当然,大多数库类型,例如字符串和列表已经实现了__eq__,这可能是比较标题适合您的原因(它们是字符串吗?)。

有关详细信息,请参阅python documentation 以下是__eq__的{​​{3}}。

答案 2 :(得分:5)

set intersection会为此做的。

>>> x=[1,2,3,4]
>>> y=[3,4,5,6]
>>> for i in set(x) & set(y):
...     print "item %d in both lists" %i
...
item 3 in both lists
item 4 in both lists

答案 3 :(得分:4)

查找出现在两个列表中的对象:

l1 = [1,2,3,4,5]
l2 = [3,4,5]
common = set(l1).intersection(set(l2))

将其与对象建议的__eq__实现相结合。

答案 4 :(得分:3)

您需要编写__eq__函数来定义如何比较对象的相等性。如果你想要排序,那么你应该有一个__cmp__函数,并且就__eq__而言最有意义地实现__cmp__

def __eq__(self, other):
    return cmp(self, other) == 0

您可能也应该实现__hash__,如果您计划将对象放入集合或字典中,那么您肯定应该这样做。对象的默认__hash__是id(),这有效地使所有对象都是唯一的(即唯一性不基于对象内容)。

我为一个进行这种等价比较的类编写了一个基类/接口。您可能会发现它很有用:

class Comparable(object):
    def attrs(self):
        raise Exception("Must be implemented in concrete sub-class!")
    def __values(self):
        return (getattr(self, attr) for attr in self.attrs())
    def __hash__(self):
        return reduce(lambda x, y: 37 * x + hash(y), self.__values(), 0)
    def __cmp__(self, other):
        for s, o in zip(self.__values(), other.__values()):
            c = cmp(s, o)
            if c:
                return c
        return 0
    def __eq__(self, other):
        return cmp(self, other) == 0
    def __lt__(self, other):
        return cmp(self, other) < 0
    def __gt__(self, other):
        return cmp(self, other) > 0

if __name__ == '__main__':
    class Foo(Comparable):
        def __init__(self, x, y):
            self.x = x
            self.y = y
        def attrs(self):
            return ('x', 'y')
        def __str__(self):
            return "Foo[%d,%d]" % (self.x, self.y)

    def foo_iter(x):
        for i in range(x):
            for j in range(x):
                yield Foo(i, j)

    for a in foo_iter(4):
        for b in foo_iter(4):
            if a<b: print "%(a)s < %(b)s" % locals()
            if a==b: print "%(a)s == %(b)s" % locals()
            if a>b: print "%(a)s > %(b)s" % locals()

派生类必须实现attrs(),它返回对象的属性的元组或列表,这些属性有助于其身份(即,使其成为现实的不变属性)。最重要的是,代码在有多个属性的情况下正确处理等价,而这通常是错误的旧代码。

答案 5 :(得分:2)

matches = [x for x in listA if x in listB]

答案 6 :(得分:0)

尝试以下方法:

list1 = [item1, item2, item3]
list2 = [item3, item4, item5]
for item in list1:
    if item in list2:
        print "item %s in both lists" % item