Удалить дубликаты в списке объектов с помощью Python
У меня есть список объектов, и у меня есть таблица db, полная записей. Мой список объектов имеет атрибут title, и я хочу удалить любые объекты с дублирующимися заголовками из списка (оставив оригинал).
Затем я хочу проверить, есть ли в моем списке объектов какие-либо дубликаты любых записей в базе данных, и если это так, удалите эти элементы из списка, прежде чем добавлять их в базу данных.
Я видел решения для удаления дубликатов из списка вроде этого: myList = list(set(myList))
, но я не уверен, как это сделать со списком объектов?
Мне также нужно поддерживать порядок моего списка объектов. Я также думал, может быть, я мог бы использовать difflib
для проверки различий в названиях.
Ответы
Ответ 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]
вот оно!:)