开发者

Python check if object is in list of objects

I have a list of objects in 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 th开发者_StackOverflowe attributes if I don't have to.

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:

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.


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.

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?).

For further information see the python documentation.
Here is a random example for __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.


You need to write an __eq__ function to define how to compare objects for equality. If you want sorting, then yo should have a __cmp__ function, and it makes the most sense to implement __eq__ in terms of __cmp__.

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. The default __hash__ for objects is id(), which effectively makes all objects unique(i.e. uniqueness is not based on object contents).

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 (i.e. unchanging attributes that make it what it is). 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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜