Проверка Python, если объект находится в списке объектов - PullRequest
18 голосов
/ 01 апреля 2010

У меня есть список объектов в Python. У меня тогда есть другой список объектов. Я хочу просмотреть первый список и посмотреть, появляются ли какие-либо элементы во втором списке.

Я думал, что могу просто сделать

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

Однако, похоже, это не работает. Хотя, если я сделаю:

if item1.title == item2.title:

все работает хорошо. У меня есть больше атрибутов, чем это, хотя, поэтому я не хочу делать 1 большой оператор if, сравнивая все атрибуты, если мне не нужно.

Может ли кто-нибудь дать мне помощь или совет относительно того, что я могу сделать, чтобы найти объекты, которые появляются в обоих списках.

Спасибо

Ответы [ 7 ]

29 голосов
/ 01 апреля 2010

Предполагая, что ваш объект имеет только атрибут title, относящийся к равенству, вы должны реализовать метод __eq__ следующим образом:

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

Конечно, если у вас есть больше атрибутовотносящиеся к равенству, вы должны включить и их.Вы также можете рассмотреть возможность реализации __ne__ и __cmp__ для согласованного поведения.

9 голосов
/ 01 апреля 2010

Если объекты не совпадают, вам необходимо реализовать метод __eq__, чтобы Python мог определить, когда 2 объекта фактически равны.

Конечно, в большинстве типов библиотек, таких как строки и списки, уже реализовано __eq__, что может быть причиной того, что сравнение названий работает для вас (это строки?).

Для получения дополнительной информации см. Документацию python .
Вот случайный пример для __eq__.

5 голосов
/ 01 апреля 2010

установить пересечение сделает для этого.

>>> 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
4 голосов
/ 01 апреля 2010

Поиск объектов, которые появляются в обоих списках:

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

Объедините это с реализацией __eq__ на объекте, как предлагали другие.

3 голосов
/ 01 апреля 2010

Вам нужно написать функцию __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(), который возвращает кортеж или список атрибутов объекта, которые вносят вклад в его идентичность (то есть неизменные атрибуты, делающие его таким, какой он есть). Самое главное, что код правильно обрабатывает эквивалентность, когда есть несколько атрибутов, и это старый код школы, который часто выполняется неправильно.

2 голосов
/ 01 апреля 2010
matches = [x for x in listA if x in listB]
0 голосов
/ 01 апреля 2010

Попробуйте следующее:

list1 = [item1, item2, item3]
list2 = [item3, item4, item5]
for item in list1:
    if item in list2:
        print "item %s in both lists" % item
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...