Python

Люди помогите, я вообще не понимаю что происходит.

В общем решил написать простой код. Текст задания был следующим: дается две строки с числами, сделать из них список, удалить их пересечения (значения там повторялись, через set делать не вариант) из первого списка и вывести его на экран. Строки в примере были
'3 9 -2 2 -2 4 -3 1 8' и '-10 -3 6 -10 0 -1 1 8'
Не пойму, почему в выводе добавляется еще 1. (Должен быть [3, 9, -2, 2, -2, 4], а у меня [3, 9, -2, 2, -2, 4, 1].)
 a, b = [list(map(int, (input().split()))) for i in range(2)] 

for i in a:
if i in b:
a.remove(i)
print(a)
Поставь print(i, a) в каждой итерации, и поймёшь динамику развития болезни, хе-хе.

Вообще, модифицировать коллекцию, по которой (или по индексам которой) идёт цикл for, - плохая идея. Последствия, в зависимости от языка, могут быть самыми непредсказуемыми.

Для решения есть несколько типовых подходов:

1) Не трогать исходную коллекцию, а результат собирать в копию, сразу фильтруя элементы:
 a = (int(s) for s in input().split())
b = {int(s) for s in input().split()}
c = (n for n in a if n not in b)
print(*c)
(обращаем внимание, что тут 'a' - итератор, а не коллекция, т.к. пробежать надо всего один раз, и для этого хранить список не нужно; а 'b' - множество, т.к. в нём порядок неважен, а скорость поиска важна; 'c' - тоже итератор и по тем же соображениям)

2) Скопировать коллекцию и итерироваться по одному экземпляру, а удалять из другого:
 a = [int(s) for s in input().split()]
b = {int(s) for s in input().split()}
c = a.copy()
for i in a:
if i in b:
c.remove(i)
print(*c)
Тут мы бежим по исходному списку, а удаляем из копии. Это менее эффективный вариант, чем предыдущий, т.к. много лишних движений (добавили, потом удалять), да и удаление из середины списка - неэффективная операция. Кстати, удаление по значению из списка тоже неэффективно, т.к. придётся пробежать в среднем половину элементов, чтобы найти нужный. И сам список мы храним, получается, дважды.

3) Итерироваться по индексам и с конца: удаление не затронет элементы с меньшими индексами:
 a = [int(s) for s in input().split()]
b = {int(s) for s in input().split()}
for i in range(len(a) - 1, -1, -1):
if a[i] in b:
a.pop(i)
print(*a)
Плюс, по сравнению с предыдущим вариантом, получается в том, что не надо копировать список. А остальные недостатки остаются.

4) Крутить счётчик цикла вручную. Если элемент удаляется, то индексы следующих сместятся к началу, поэтому инкремент не нужен, а если не удаляется, то делаем +1. Этот вариант чатгптшный бот выше приводил. Здесь эффективность - такая же, как и в варианте (3).

В реальных программах, где важна производительность, обычно применяется вариант (1): он обеспечивает однократный пробег по списку, и у него линейная сложность. У остальных алгоритмов, включая твой, сложность - квадратичная (внутри пробега по элементам - ещё один пробег для удаления).
Диас Абигузин)))
Диас Абигузин)))
87 571
Лучший ответ
Потому, что ты удаляешь элементы из того массива, по которому производишь итерацию. Это всегда приводит к неприяным глюкам. Самый простой способ исправления твоего решения - производить итерацию не по оригинальному массиву, а по его копии:
 for i in a[:]: # итерируем не a, а копию a
if i in b:
a.remove(i)
ИЖ
Иван Жовба
80 161
А второй список почему игнорируете? Вы только из а удалили то, что есть в b, а то что есть в b, но нет в a, не добавили
 a, b = [list(map(int, input().split())) for i in range(2)] 
c = []
for i in a:
if i not in b:
c.append(i)
for i in b:
if i not in a:
c.append(i)
print(c)
Роман Макаров
Роман Макаров
55 095
При удалении элементов из списка, происходит изменение индексов элементов в списке, что может привести к тому, что программа может пропустить некоторые элементы при проходе цикла for.
Поэтому лучше использовать цикл while вместо for.

Вот исправленный код:
 a, b = [list(map(int, input().split())) for i in range(2)] 
i = 0
while i < len(a):
if a[i] in b:
a.remove(a[i])
else:
i += 1
print(a)
В этом коде используется цикл while и переменная i, которая указывает на текущий индекс элемента в списке a. Если a[i] есть в списке b, то элемент удаляется из списка a с помощью метода remove(). Иначе, индекс i увеличивается на 1, чтобы перейти к следующему элементу. Таким образом, мы можем безопасно проходить по всем элементам списка a, даже если некоторые элементы были удалены из него.
Никита Панкратов спасибо чат гэпэтэ