Подтвердить что ты не робот

Удалить дубликаты в списке объектов с помощью Python

У меня есть список объектов, и у меня есть таблица db, полная записей. Мой список объектов имеет атрибут title, и я хочу удалить любые объекты с дублирующимися заголовками из списка (оставив оригинал).

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

Я видел решения для удаления дубликатов из списка вроде этого: myList = list(set(myList)), но я не уверен, как это сделать со списком объектов?

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

4b9b3361

Ответ 1

set(list_of_objects) удалит только дубликаты, если вы знаете, что такое дубликат, т.е. вам нужно определить уникальность объекта.

Чтобы сделать это, вам нужно сделать объект хешируемым. Вам необходимо определить методы __hash__ и __eq__, вот как это сделать:

http://docs.python.org/glossary.html#term-hashable

Хотя вам, вероятно, нужно будет определить метод __eq__.

EDIT: как реализовать метод __eq__:

Вам следует знать, как я уже упоминал, определение уникальности вашего объекта. Предположим, что у нас есть Книга с атрибутами author_name и title, что их комбинация уникальна (так что у нас может быть много книг Стивена Кинга, и многие книги под названием The Shining, но только одна книга под названием The Shining by Stephen King), то реализация выглядит следующим образом:

def __eq__(self, other):
    return self.author_name==other.author_name\
           and self.title==other.title

Точно так же я иногда реализую метод __hash__:

def __hash__(self):
    return hash(('title', self.title,
                 'author_name', self.author_name))

Вы можете проверить, что если вы создадите список из двух книг с одним и тем же автором и названием, объекты книги будут совпадать (с оператором is) и равным (с оператором ==). Кроме того, когда используется set(), он удалит одну книгу.

РЕДАКТИРОВАТЬ. Это один из моих старых моих предшественников, но я только сейчас замечаю, что он имеет ошибку, которая исправлена ​​с помощью зачеркивания в последнем абзаце: объекты с тем же hash() не будут дайте True по сравнению с is. Хеширование объекта используется, однако, если вы собираетесь использовать их как элементы набора или как ключи в словаре.

Ответ 2

Поскольку они не хешируются, вы не можете использовать набор напрямую. Заголовки должны быть хотя.

Здесь первая часть.

seen_titles = set()
new_list = []
for obj in myList:
    if obj.title not in seen_titles:
        new_list.append(obj)
        seen_titles.add(obj.title)

Вам нужно будет описать, какую базу данных /ORM и т.д. вы используете для второй части.

Ответ 3

Это кажется довольно минимальным:

new_dict = dict()
for obj in myList:
    if obj.title not in new_dict:
        new_dict[obj.title] = obj

Ответ 4

Для этого __hash__ и __hash__ и __eq__.

__hash__ необходим для добавления объекта в набор, поскольку наборы python реализованы в виде хеш-таблиц. По умолчанию неизменяемые объекты, такие как числа, строки и кортежи, являются хэшируемыми.

Однако коллизии хэшей (два разных объекта, хэширующие одно и то же значение) неизбежны из-за принципа "голубиных отверстий". Таким образом, два объекта нельзя различить только по их хешу, и пользователь должен указать свою собственную функцию __eq__. Таким образом, фактическая хеш-функция, предоставляемая пользователем, не является критически важной, хотя лучше всего попытаться избежать коллизий хеш-функций для производительности (см. Какой правильный и хороший способ реализовать __hash __()?).

Ответ 5

Еще один пример, как мы можем это сделать:

objs = [{'id': 1}, {'id': 2}, {'id': 3}, {'id': 1}]

res = []

for obj in objs:
    if obj['id'] not in [obj['id'] for obj in res]:
        res.append(obj)

print(res)

# output: [{'id': 1}, {'id': 2}, {'id': 3}]

Ответ 6

Если вы хотите сохранить исходный порядок, используйте его:

seen = {}
new_list = [seen.setdefault(x, x) for x in my_list if x not in seen]

Если вы не заботитесь о заказе, используйте его:

new_list = list(set(my_list))

Ответ 7

Его довольно легко freinds: -

  

a = [5,6,7,32,32,32,32,32,32,32,32]

         

a = list (set (a))

         

print (a)

  
[5,6,7,32]

вот оно!:)