7 методов устранения повторяющихся элементов в списках Python
В Python часто возникают ситуации, когда необходимо очистить список от дублирующихся значений, чтобы остались только неповторяющиеся, уникальные значения его элементов. В этой статье рассмотрим несколько эффективных подходов для решения этой задачи, и сравним их по скорости выполнения.
1. Прямой перебор значений
Определяем новый пустой список, затем в цикле идем по элементам списка, и если текущий элемент не содержится в новом списке, то добавляем его:
my_list = ["a", "a", "b", "a", "c", "c", "a", "b", "a",]
new_list = []
for item in my_list:
if item not in new_list:
new_list.append(item)
print(new_list) # Вывод: ["a", "b", "c"]
2. Использование множеств (set) для удаления дубликатов
Самый простой способ — преобразование списка в множество, а затем обратно в список:
original_elements = [10, 20, 30, 20, 40, 10, 50]
unique_items = list(set(original_elements))
print(unique_items) # Вывод: [40, 10, 50, 20, 30]
Важно: Порядок элементов не сохраняется, так как множества в Python неупорядочены.
3. Сохранение порядка с помощью словаря
Если порядок элементов важен, можно использовать словарь:
items = ["apple", "banana", "apple", "orange", "banana"]
filtered_list = list(dict.fromkeys(items))
print(filtered_list) # Вывод: ['apple', 'banana', 'orange']
4. Использование спискового включения (list comprehension)
Метод альтернативный первому — перебор элементов с проверкой на уникальность:
data = [1, 2, 2, 3, 4, 4, 5]
cleaned_data = []
[cleaned_data.append(x) for x in data if x not in cleaned_data]
print(cleaned_data) # Вывод: [1, 2, 3, 4, 5]
5. С использованием enumerate():
Функция enumerate() перебирает элементы списка вместе с их индексами, предоставляя кортеж (index, element). Здесь n — это индекс, а i — значение элемента. Условие if i not in data[:n] проверяет, присутствует ли текущий элемент i среди всех предыдущих элементов (до позиции n включительно). Если он там отсутствует, элемент считается уникальным и включается в результирующий список. :
data = [1, 2, 2, 3, 4, 4, 5]
cleaned_data = []
cleaned_data = [i for n, i in enumerate(data) if i not in data[:n]]
print(cleaned_data) # Вывод: [1, 2, 3, 4, 5]
6. Применение библиотеки Pandas
Для работы с большими массивами данных удобно использовать Pandas:
import pandas as pd
numbers = [5, 5, 10, 15, 10, 20]
series = pd.Series(numbers)
result = series.drop_duplicates().tolist()
print(result) # Вывод: [5, 10, 15, 20]
7. Применение OrderedDict из стандартного модуля collections
Можно использовать специальный класс collections.OrderedDict, представляющий собой словарь (dict), сохраняющий порядок вставки элементов:
from collections import OrderedDict as od
data_list = [3, 5, 1, 5, 3, 2]
cleaned_list = list(od.fromkeys(data_list))
print(cleaned_list) # Вывод: [3, 5, 1, 2]
Скорость работы методов
Сравним скорость работы методов. Для этого используем стандартный модуль time и его метод time():
import random
import pandas as pd
from collections import OrderedDict as od
import time
# Генерируем список из 300000 случайных целых чисел от 1 до 10
data = [random.randint(1, 10) for _ in range(300000)]
start_time = time.time()
new_list = []
for item in data:
if item not in new_list:
new_list.append(item)
end_time = time.time()
execution_time = end_time - start_time
print(execution_time)
start_time = time.time()
unique_items = list(set(data))
end_time = time.time()
execution_time = end_time - start_time
print(execution_time)
start_time = time.time()
filtered_list = list(dict.fromkeys(data))
end_time = time.time()
execution_time = end_time - start_time
print(execution_time)
start_time = time.time()
cleaned_data = []
[cleaned_data.append(x) for x in data if x not in cleaned_data]
end_time = time.time()
execution_time = end_time - start_time
print(execution_time)
start_time = time.time()
cleaned_data = []
cleaned_data = [i for n, i in enumerate(data) if i not in data[:n]]
end_time = time.time()
execution_time = end_time - start_time
print(execution_time)
start_time = time.time()
series = pd.Series(data)
result = series.drop_duplicates().tolist()
end_time = time.time()
execution_time = end_time - start_time
print(execution_time)
start_time = time.time()
cleaned_list = list(od.fromkeys(data))
end_time = time.time()
execution_time = end_time - start_time
print(execution_time)
Результат выполнения программы:
0.09872746467590332
0.007032155990600586
0.010793924331665039
0.03624248504638672
203.83486247062683
0.2821784019470215
0.02706289291381836
Вывод
Выбор метода зависит от конкретной задачи. Для максимальной скорости подойдут множества (метод 2). Если важен порядок элементов в списке — используйте словари (метод 3) или OrderedDict (метод 7). Остальные методы подойдут для небольших массивов данных. Значительно хуже всех показал себя метод с использованием enumerate(). Он оригинален и работает для малых массивах, но скорость выполнения значительно возрастает при увеличении размера массива./p>