Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

Удаление повторяющихся чисел из списка через цикл в Python

ArtS Ученик (221), закрыт 1 год назад
Доброго дня.
Я совсем новичок. На Codewars попалась задача, где надо два списка, состоящих только из целых чисел, объединить в один, отсортировать по возрастанию и удалить повторяющиеся числа. Я знаю, что список можно превратить в множество, а потом обратно в список. Но решил сделать это через цикл, и почему-то в некоторых случаях у меня какое-либо из чисел остаётся в двух экземплярах. Вот мой код:

def nums(x,y):
i = x+y
i.sort(reverse=False)
for a in i:
if i.count(a)>1:
i.remove(a)
return i

В данном случае, программа оставляет два числа со значением (-18), если в качестве переменных задаются следующие списки:
x=[100, 99, 98, 97, 91, 85, 84, 80, 79, 77, 76, 74, 70, 68, 67, 66, 64, 63, 63, 61, 59, 56, 56, 54, 53, 52, 49, 41, 40, 39, 36, 35, 30, 25, 16, 13, 13, 6, 6, 6, 2, -3, -5, -12, -14, -18, -18, -18, -19, -19, -19, -20, -23, -26, -26, -26, -28, -32, -34, -34, -40, -40, -44, -46, -46, -49, -54, -55, -56, -57, -61, -62, -62, -64, -65, -65, -66, -68, -70, -70, -71, -72, -76, -77, -77, -79, -82, -85, -87, -88, -90, -92, -99]
y=[100, 99, 66, 60, 58, 50, 47, 44, 38, 37, 36, 36, 26, 14, -6, -46, -51, -53, -54, -66, -71, -75, -81, -84, -87]
При этом как видите есть три числа (-19) и остаётся только одно.
Подскажите пожалуйста где ошибка и почему остаётся одно задвоенное число. Спасибо.
Лучший ответ
♡$ⴎG@r₱u₷sყ♡ Искусственный Интеллект (322736) 1 год назад
Добрый день!

Проблема в том, что при удалении элемента из списка во время итерации, индексы следующих элементов смещаются, и цикл может пропустить некоторые элементы. Чтобы это исправить, можно итерироваться по копии списка:

 def nums(x, y): 
i = x + y
i.sort()
for a in i[:]: # Используем копию списка i[:]
if i.count(a) > 1:
i.remove(a)
return i


Такой подход сработает, но он неэффективен, так как `count()` и `remove()` работают за O(n), и в худшем случае получается O(n^3). Лучше использовать множество для отслеживания уникальных чисел:

 def nums(x, y): 
i = x + y
i.sort()
unique_nums = set()
result = []
for a in i:
if a not in unique_nums:
result.append(a)
unique_nums.add(a)
return result


Этот код будет работать эффективнее.
ArtSУченик (221) 1 год назад
Вот про это "при удалении элемента из списка во время итерации, индексы следующих элементов смещаются, и цикл может пропустить некоторые элементы" - не знал. Возьму на заметку. Спасибо.
ArtS, если удаляете в цикле, "бегите" с конца в начало, тогда проблем с индексами не будет
ПапаВысший разум (154726) 1 год назад
Одной из характерных черт питоновских "программистов" является полное непонимание, что делается под капотом написанного ими кода, и как это влияет на асимптотику.
DmitryПросветленный (23147) 1 год назад
Худший случай поиска элемента в set - O(n). Думаю, раз в задании есть сортировка, то ожидают какое-то такое решение:
 def nums(x, y):
lst = x + y
lst.sort()
i = 0
for j in range(1, len(lst)):
if lst[i] != lst[j]:
i += 1
lst[i] = lst[j]
del lst[i + 1:]
return lst
Можно цикл на groupby из itertools заменить
Остальные ответы
Золотой Самокат Профи (615) 1 год назад
Проблема заключается в том, что вы изменяете список i во время итерации по нему, используя i.remove(a), что может привести к непредсказуемому поведению и пропуску некоторых повторяющихся чисел.

Вместо этого вы можете использовать множество (set) для удаления дубликатов и затем преобразовать его обратно в список. Вот пример исправленной функции:

def nums(x, y):
result_set = set(x + y) # объединяем оба списка и преобразуем в множество, чтобы удалить дубликаты
result_list = list(result_set) # преобразуем множество обратно в список
result_list.sort() # сортируем список
return result_list


Этот код объединяет оба списка, удаляет дубликаты с помощью множества, затем преобразует обратно в список и сортирует его. Вы можете использовать эту функцию вместо вашей, чтобы получить правильный результат.
ArtSУченик (221) 1 год назад
Про "изменяете список i во время итерации по нему, используя i.remove(a), что может привести к непредсказуемому поведению и пропуску некоторых повторяющихся чисел" не знал. Спасибо.
Папа Высший разум (154726) ArtS, посмотри на себя, товарищ. Ты разговариваешь с нейросетью. Это очень, очень плохой признак.
S.H.I. Оракул (74197) 1 год назад
 def nums(x, y): 
i = x + y # Объединение списков
i.sort() # Сортировка списка
# Использование нового списка для хранения уникальных элементов
unique_i = []
for a in i:
if a not in unique_i:
unique_i.append(a)
return unique_i
Юрий Семыкин Искусственный Интеллект (218891) 1 год назад
У всех одна и та же алгоритмическая ошибка. Надо не "if i.count(a) > 1:", а "while i.count(a) > 1:"
иначе у вас удалется только 1 элемент, а если одинаковых больше 2х, то ошибка и возникает.
Похожие вопросы