简体   繁体   English

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

[英]Python check if object is in list of objects

I have a list of objects in Python. 我在Python中有一个对象列表。 I then have another list of objects. 然后我有另一个对象列表。 I want to go through the first list and see if any items appear in the second list. 我想浏览第一个列表,看看是否有任何项目出现在第二个列表中。

I thought I could simply do 我以为我可以做到

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

However this does not seem to work. 然而,这似乎不起作用。 Although if I do: 虽然我这样做:

if item1.title == item2.title:

it works okay. 它工作正常。 I have more attributes than this though so don't really want to do 1 big if statement comparing all the attributes if I don't have to. 我有比这更多的属性,所以不要真的想做一个大的if语句比较所有的属性,如果我不需要。

Can anyone give me help or advise on what I can do to find the objects which appear in both lists. 任何人都可以给我帮助或建议我可以做什么来找到两个列表中出现的对象。

Thanks 谢谢

Assuming that your object has only a title attribute which is relevant for equality, you have to implement the __eq__ method as follows: 假设您的对象只有一个与相等相关的title属性,您必须按如下方式实现__eq__方法:

class YourObject:
    [...]
    def __eq__(self, other):
        return self.title == other.title

Of course if you have more attributes that are relevant for equality, you must include those as well. 当然,如果您有更多与平等相关的属性,那么您也必须包含这些属性。 You might also consider implementing __ne__ and __cmp__ for consistent behaviour. 您也可以考虑实现__ne____cmp__以保持一致的行为。

In case the objects are not the same instance, you need to implement the __eq__ method for python to be able to tell when 2 objects are actually equal. 如果对象不是同一个实例,则需要为python实现__eq__方法,以便能够判断2个对象实际上是否相等。

Of course that most library types, such as strings and lists already have __eq__ implemented, which may be the reason comparing titles works for you (are they strings?). 当然,大多数库类型,例如字符串和列表已经实现了__eq__ ,这可能是比较标题适合你的原因(它们是字符串吗?)。

For further information see the python documentation . 有关更多信息,请参阅python文档
Here is a random example for __eq__ . 这是__eq__随机示例

set intersection will do for that. 集合交叉将为此做。

>>> 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

Finding objects who appear in both lists: 查找出现在两个列表中的对象:

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

Combine this with the __eq__ implementation on the object as the others suggested. 将其与对象上的__eq__实现相结合,如其他人所建议的那样。

You need to write an __eq__ function to define how to compare objects for equality. 您需要编写__eq__函数来定义如何比较对象的相等性。 If you want sorting, then yo should have a __cmp__ function, and it makes the most sense to implement __eq__ in terms of __cmp__ . 如果你想要排序,那么你应该有一个__cmp__函数,并且根据__cmp__实现__eq__是最有意义的。

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

You should probably also implement __hash__ , and you definitely should if you plan to put your objects into a set or dictionary. 您可能还应该实现__hash__ ,如果您计划将对象放入集合或字典中,那么您肯定应该这样做。 The default __hash__ for objects is id(), which effectively makes all objects unique(ie uniqueness is not based on object contents). 对象的默认__hash__是id(),它有效地使所有对象都是唯一的(即唯一性不基于对象内容)。

I wrote a base class/interface for a class that does this sort of equivalence comparison. 我为一个类做了基类/接口,它进行了这种等价比较。 You may find it useful: 您可能会发现它很有用:

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()

The derived class must implement attrs() that returns a tuple or list of the object's attributes that contribute to its identity (ie unchanging attributes that make it what it is). 派生类必须实现attrs() ,它返回对象的属性的元组或列表,这些属性有助于其身份(即,使其成为现实的不变属性)。 Most importantly, the code correctly handles equivalence where there are multiple attributes, and this is old school code that is often done incorrectly. 最重要的是,代码正确处理具有多个属性的等效性,这是通常不正确的旧学校代码。

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

Try the following: 请尝试以下方法:

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

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

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