Использование цикла for для удаления элементов из списка не работает, но использование понимания списка нормально - PullRequest
1 голос
/ 07 июля 2019

ОК, эта проблема действительно решена, но я все еще хочу знать ПОЧЕМУ .Я пытаюсь удалить элементы из двумерного массива, и вот код:

print("adj in the while loop: ", adj)
for z in adj:
    print("for loop: ", z)
    if z[-1] is True:
        adj.remove(z)
result += 1
print("adj after all execution: ", adj)

Вывод на консоль:

adj in the while loop: [[1, True], [0, 2, True], [1, True]]
for loop: [1, True]
for loop: [1, True]
adj after all execution: [[0, 2, True]]

Это не работает, как предполагалось.Правильный вывод после выполнения должен быть [].

Так что я начинаю редактировать код, используя списочное понимание.

Код для составления списка:

adj = [z for z in adj if z[-1] is not True]

Работает как задумано.Вывод [].

Это меня смущает.Почему эти два, казалось бы, идентичных метода дают разные результаты?Кто-нибудь может мне это объяснить?

Ответы [ 3 ]

4 голосов
/ 07 июля 2019

Эти два метода не идентичны.В понимании списка вы никогда не позвоните adj.remove(z).

Понимание списка создает новый список, поскольку он повторяется по adj, а затем вы назначаете этот (пустой) список обратно adj, как только это будет сделано.Он не изменяется adj во время итерации, только после последней итерации.

2 голосов
/ 07 июля 2019

Вы можете определенно использовать .remove(), но перебираете копию оригинала, а не сам оригинал:

adj = [[1, True], [0, 2, True], [1, True]]

for z in adj[:]:
    print("for loop: ", z)
    if z[-1] is True:
        adj.remove(z)
result += 1
print("adj after all execution: ", adj)

, который печатает пустой список.

Здесь мыпереберите копию, но удалите элементы из оригинала.Это позволяет избежать расхождений, которые вы видите с вашим кодом.

1 голос
/ 08 июля 2019

Итерация по list и одновременно с его внутренним блоком, если вы используете метод remove или append для элемента, это неправильный способ сделать это.В принципе лучше поменять кодировку на другой способ.Как предложил Остин в своем коде или использовать отдельный индекс вместо итеративного индекса или элемента.

То есть

adj = [[3, 4, 5, False], [8, 7, False], [0, True], [-1, False], [1, True], [0, 2, False], [0, 2, True], [1, True], [4, False]]

del_index = 0
for i in range(len(adj)):
    print("for loop: ", adj[del_index])
    if adj[del_index][-1] is True:
        adj.remove(adj[del_index])
    else:
        del_index+=1
print("adj after all execution: ", adj)

Для этой цели можно применить фильтр

filter(lambda elem: elem[-1] is True, adj)

Это может привести к сбою в вашей системе, так как элемент добавления в список и в то же время повторяется по тому же.

crash_my_system = [0]
for i in crash_my_system: crash_my_system.append(i+1)

Это верно не только для List.это общее для всех изменяемых структур данных, таких как Dict.См. блог Кристофа Цвершке

...