Удаление дубликатов в списках
в значительной степени мне нужно написать программу, чтобы проверить, есть ли в списке дубликаты, и если это так, он удаляет их и возвращает новый список с элементами, которые не были дублированы/удалены. Это то, что у меня есть, но честно говоря, я не знаю, что делать.
def remove_duplicates():
t = ['a', 'b', 'c', 'd']
t2 = ['a', 'c', 'd']
for t in t2:
t.append(t.remove())
return t
30 ответов:
В Python 2.7, новый способ удаления дубликатов из iterable, сохраняя его в исходном порядке:
>>> from collections import OrderedDict >>> list(OrderedDict.fromkeys('abracadabra')) ['a', 'b', 'r', 'c', 'd']В Python 3.5, OrderedDict имеет реализацию C. Мои тайминги показывают, что теперь это самый быстрый и самый короткий из различных подходов для Python 3.5.
В Python 3.6, обычный дикт стал одновременно упорядоченным и компактным. (Эта функция выполняется для CPython и PyPy, но не может в других реализациях). Это дает нам новый быстрый способ дедупликации при сохранении порядка:
>>> list(dict.fromkeys('abracadabra')) ['a', 'b', 'r', 'c', 'd']В Python 3.7, регулярный dict гарантированно упорядочен во всех реализациях. Итак, самое короткое и быстрое решение:
>>> list(dict.fromkeys('abracadabra')) ['a', 'b', 'r', 'c', 'd']
это один-лайнер:
list(set(source_list))будет делать трюк.A
setэто то, что не может быть дубликатов.обновление: метод сохранения порядка состоит из двух строк:
from collections import OrderedDict OrderedDict((x, True) for x in source_list).keys()здесь мы используем тот факт, что
OrderedDictзапоминает порядок вставки ключей и не изменяет его при обновлении значения в определенном ключе. ВставляемTrueкак значения, но мы могли бы вставить что-нибудь, значения просто не используются. (setработы какdictс игнорированием значения.)
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8] >>> t [1, 2, 3, 1, 2, 5, 6, 7, 8] >>> s = [] >>> for i in t: if i not in s: s.append(i) >>> s [1, 2, 3, 5, 6, 7, 8]
Если вы не заботитесь о заказе, просто сделать это:
def remove_duplicates(l): return list(set(l))A
setгарантированно не имеет дубликатов.
чтобы создать новый список, сохраняя порядок первых элементов дубликатов в
L
newlist=[ii for n,ii in enumerate(L) if ii not in L[:n]]if L=[1, 2, 2, 3, 4, 2, 4, 3, 5]затемnewlistбудет[1,2,3,4,5]это проверяет каждый новый элемент не появился ранее в списке перед его добавлением. Также он не нуждается в импорте.
коллега отправил принятый ответ как часть своего кода мне для просмотра кода сегодня. Хотя я, конечно, восхищаюсь элегантностью ответа на вопрос, я не доволен выступлением. Я пробовал это решение (я использую set чтобы сократить время поиска)
def ordered_set(in_list): out_list = [] added = set() for val in in_list: if not val in added: out_list.append(val) added.add(val) return out_listдля сравнения эффективности я использовал случайную выборку из 100 целых чисел-62 были уникальными
from random import randint x = [randint(0,100) for _ in xrange(100)] In [131]: len(set(x)) Out[131]: 62вот результаты измерений
In [129]: %timeit list(OrderedDict.fromkeys(x)) 10000 loops, best of 3: 86.4 us per loop In [130]: %timeit ordered_set(x) 100000 loops, best of 3: 15.1 us per loopНу и что произойдет, если удаляются из раствора?
def ordered_set(inlist): out_list = [] for val in inlist: if not val in out_list: out_list.append(val) return out_listрезультат не так плох, как с OrderedDict, но все же более 3 раз оригинального решения
In [136]: %timeit ordered_set(x) 10000 loops, best of 3: 52.6 us per loop
есть также решения с использованием панд и Numpy. Они оба возвращают массив numpy, поэтому вы должны использовать функцию
.tolist()если вы хотите получить список.t=['a','a','b','b','b','c','c','c'] t2= ['c','c','b','b','b','a','a','a']решение панд
С помощью функции панды
unique():import pandas as pd pd.unique(t).tolist() >>>['a','b','c'] pd.unique(t2).tolist() >>>['c','b','a']решение включает в себя
С помощью функции numpy
unique().import numpy as np np.unique(t).tolist() >>>['a','b','c'] np.unique(t2).tolist() >>>['a','b','c']обратите внимание, что numpy.unique () также сортирует значения. Итак, список
t2возвращает отсортированный. Если вы хотите, чтобы порядок сохранялся, Используйте как в ответ:_, idx = np.unique(t2, return_index=True) t2[np.sort(idx)].tolist() >>>['c','b','a']решение не так элегантно по сравнению с другими, однако, по сравнению с пандами.unique (), numpy.unique () позволяет также проверить уникальность вложенных массивов вдоль одной выбранной оси.
легко и просто:
myList = [1, 2, 3, 1, 2, 5, 6, 7, 8] cleanlist = [] [cleanlist.append(x) for x in myList if x not in cleanlist]выход:
>>> cleanlist [1, 2, 3, 5, 6, 7, 8]
Я имел dict в моем списке, поэтому я не мог использовать вышеуказанный подход. Я получил ошибку:
TypeError: unhashable type:Так что если вы заботитесь о ордер и / или некоторые элементы unhashable. Тогда вы можете найти это полезным:
def make_unique(original_list): unique_list = [] [unique_list.append(obj) for obj in original_list if obj not in unique_list] return unique_listнекоторые могут считать, что понимание списка с побочным эффектом не является хорошим решением. Вот альтернатива:
def make_unique(original_list): unique_list = [] map(lambda x: unique_list.append(x) if (x not in unique_list) else False, original_list) return unique_list
попробуйте использовать наборы:
import sets t = sets.Set(['a', 'b', 'c', 'd']) t1 = sets.Set(['a', 'b', 'c']) print t | t1 print t - t1
вы также можете сделать это:
>>> t = [1, 2, 3, 3, 2, 4, 5, 6] >>> s = [x for i, x in enumerate(t) if i == t.index(x)] >>> s [1, 2, 3, 4, 5, 6]причина того, что вышеуказанные работы заключается в том, что
indexметод возвращает только первый индекс элемента. Повторяющиеся элементы имеют более высокие показатели. См.здесь:список.индекс (x [, начало [, конец]])
Возвращает отсчитываемый от нуля индекс в списке первый элемент, значение которого равно x. вызывает ValueError, если нет такой пункт.
все подходы к сохранению порядка, которые я видел здесь до сих пор, либо используют наивное сравнение (с O(n^2) временной сложностью в лучшем случае), либо тяжелый вес
OrderedDicts/set+listкомбинации, которые ограничиваются hashable входов. Вот хэш-независимое O (nlogn) решение:обновление добавил
keyаргумент, документация и совместимость с Python 3.# from functools import reduce <-- add this import on Python 3 def uniq(iterable, key=lambda x: x): """ Remove duplicates from an iterable. Preserves order. :type iterable: Iterable[Ord => A] :param iterable: an iterable of objects of any orderable type :type key: Callable[A] -> (Ord => B) :param key: optional argument; by default an item (A) is discarded if another item (B), such that A == B, has already been encountered and taken. If you provide a key, this condition changes to key(A) == key(B); the callable must return orderable objects. """ # Enumerate the list to restore order lately; reduce the sorted list; restore order def append_unique(acc, item): return acc if key(acc[-1][1]) == key(item[1]) else acc.append(item) or acc srt_enum = sorted(enumerate(iterable), key=lambda item: key(item[1])) return [item[1] for item in sorted(reduce(append_unique, srt_enum, [srt_enum[0]]))]
лучший способ удаления дубликатов из списка-это использование set () функция, доступная в python, снова преобразует это набор в список
In [2]: some_list = ['a','a','v','v','v','c','c','d'] In [3]: list(set(some_list)) Out[3]: ['a', 'c', 'd', 'v']
Это один заботится о порядке без слишком много хлопот (OrderdDict и другие). Вероятно, не самый Питонический путь, ни самый короткий путь, но делает трюк:
def remove_duplicates(list): ''' Removes duplicate items from a list ''' singles_list = [] for element in list: if element not in singles_list: singles_list.append(element) return singles_list
уменьшить вариант с сохранением заказа:
предположим, что у нас есть список:
l = [5, 6, 6, 1, 1, 2, 2, 3, 4]уменьшить вариант (маломощные):
>>> reduce(lambda r, v: v in r and r or r + [v], l, []) [5, 6, 1, 2, 3, 4]5 x быстрее, но более сложные
>>> reduce(lambda r, v: v in r[1] and r or (r[0].append(v) or r[1].add(v)) or r, l, ([], set()))[0] [5, 6, 1, 2, 3, 4]объяснение:
default = (list(), set()) # user list to keep order # use set to make lookup faster def reducer(result, item): if item not in result[1]: result[0].append(item) result[1].add(item) return result reduce(reducer, l, default)[0]
ниже код прост для удаления дубликатов в списке
def remove_duplicates(x): a = [] for i in x: if i not in a: a.append(i) return a print remove_duplicates([1,2,2,3,3,4])он возвращает [1,2,3,4]
есть много других ответов, предлагающих различные способы сделать это, но они все пакетные операции, и некоторые из них выбрасывают исходный заказ. Это может быть хорошо в зависимости от того, что вам нужно, но если вы хотите перебирать значения в порядке первого экземпляра каждого значения, и вы хотите удалить дубликаты на лету против всех сразу, вы можете использовать этот генератор:
def uniqify(iterable): seen = set() for item in iterable: if item not in seen: seen.add(item) yield itemэто возвращает генератор/итератор, так что вы можете использовать его в любом месте, что вы можно использовать итератор.
for unique_item in uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]): print(unique_item, end=' ') print()выход:
1 2 3 4 5 6 7 8
если вы хотите
list, вы можете сделать это:unique_list = list(uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8])) print(unique_list)выход:
[1, 2, 3, 4, 5, 6, 7, 8]
без использования set
data=[1, 2, 3, 1, 2, 5, 6, 7, 8] uni_data=[] for dat in data: if dat not in uni_data: uni_data.append(dat) print(uni_data)
вот самое быстрое решение pythonic, которое приходит к другим, перечисленным в ответах.
использование деталей реализации оценки короткого замыкания позволяет использовать понимание списка, что достаточно быстро.
visited.add(item)всегда возвращаетNoneв результате, который оценивается какFalse, Так что правая сторонаorвсегда будет результатом такого выражения.время сам
def deduplicate(sequence): visited = set() adder = visited.add # get rid of qualification overhead out = [adder(item) or item for item in sequence if item not in visited] return out
используя set:
a = [0,1,2,3,4,3,3,4] a = list(set(a)) print aиспользуя уникальный:
import numpy as np a = [0,1,2,3,4,3,3,4] a = np.unique(a).tolist() print a
очень простой способ в Python 3:
>>> n = [1, 2, 3, 4, 1, 1] >>> n [1, 2, 3, 4, 1, 1] >>> m = sorted(list(set(n))) >>> m [1, 2, 3, 4]
В настоящее время вы можете использовать класс счетчика:
>>> import collections >>> c = collections.Counter([1, 2, 3, 4, 5, 6, 1, 1, 1, 1]) >>> c.keys() dict_keys([1, 2, 3, 4, 5, 6])
вот пример, возвращающий список без повторов с сохранением порядка. Не нуждается ни в каком внешнем импорте.
def GetListWithoutRepetitions(loInput): # return list, consisting of elements of list/tuple loInput, without repetitions. # Example: GetListWithoutRepetitions([None,None,1,1,2,2,3,3,3]) # Returns: [None, 1, 2, 3] if loInput==[]: return [] loOutput = [] if loInput[0] is None: oGroupElement=1 else: # loInput[0]<>None oGroupElement=None for oElement in loInput: if oElement<>oGroupElement: loOutput.append(oElement) oGroupElement = oElement return loOutput
проверьте это, если вы хотите удалить дубликаты (редактировать на месте, а не возвращать новый список) без использования встроенного набора, dict.ключи, uniqify, счетчик
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8] >>> for i in t: ... if i in t[t.index(i)+1:]: ... t.remove(i) ... >>> t [3, 1, 2, 5, 6, 7, 8]
Я думаю, что преобразование в set-это самый простой способ удалить дубликат:
list1 = [1,2,1] list1 = list(set(list1)) print list1
чтобы удалить дубликаты, сделайте его набором, а затем снова сделайте его списком и распечатайте/используйте его. Набор гарантированно имеет уникальные элементы. Например :
a = [1,2,3,4,5,9,11,15] b = [4,5,6,7,8] c=a+b print c print list(set(c)) #one line for getting unique elements of cвывод будет следующим (проверено в python 2.7)
[1, 2, 3, 4, 5, 9, 11, 15, 4, 5, 6, 7, 8] #simple list addition with duplicates [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 15] #duplicates removed!!
вы можете сделать это просто с помощью наборов.
Шаг 1: получить различные элементы списков
Step2 получить общие элементы списков
Step3 объединить ихIn [1]: a = ["apples", "bananas", "cucumbers"] In [2]: b = ["pears", "apples", "watermelons"] In [3]: set(a).symmetric_difference(b).union(set(a).intersection(b)) Out[3]: {'apples', 'bananas', 'cucumbers', 'pears', 'watermelons'}
def remove_duplicates(A): [A.pop(count) for count,elem in enumerate(A) if A.count(elem)!=1] return Aсписок понимание для удаления дубликатов
Comments