Вопрос-Ответ

How to modify list entries during for loop?

Как изменять записи списка во время цикла for?

Я знаю, что небезопасно изменять список во время итеративного цикла. Однако предположим, что у меня есть список строк, и я хочу удалить сами строки. Считается ли замена изменяемых значений модификацией?


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

Переведено автоматически
Ответ 1

Поскольку приведенный ниже цикл изменяет только уже виденные элементы, это было бы сочтено приемлемым:

a = ['a',' b', 'c ', ' d ']

for i, s in enumerate(a):
a[i] = s.strip()

print(a) # -> ['a', 'b', 'c', 'd']

Что отличается от:

a[:] = [s.strip() for s in a]

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

Внимание: Хотя вы можете изменять записи таким образом, вы не можете изменить количество элементов в list, не рискуя столкнуться с проблемами.

Вот пример того, что я имею в виду — удаление записи приводит к путанице в индексации с этого момента:

b = ['a', ' b', 'c ', ' d ']

for i, s in enumerate(b):
if s.strip() != b[i]: # leading or trailing whitespace?
del b[i]

print(b) # -> ['a', 'c '] # WRONG!

(Результат неверный, потому что он не удалил все элементы, которые должны были быть.)

Обновить

Поскольку это довольно популярный ответ, вот как эффективно удалять записи "на месте" (хотя это не совсем вопрос):

b = ['a',' b', 'c ', ' d ']

b[:] = [entry for entry in b if entry.strip() == entry]

print(b) # -> ['a'] # CORRECT

Смотрите Как удалять элементы из списка во время итерации?.

Ответ 2

Это считается плохой формой. Вместо этого используйте понимание списка с назначением фрагмента, если вам нужно сохранить существующие ссылки на список.

a = [1, 3, 5]
b = a
a[:] = [x + 2 for x in a]
print(b)
Ответ 3

Еще один вариант цикла for, на мой взгляд, выглядит чище, чем вариант с enumerate():

for idx in range(len(list)):
list[idx]=... # set a new value
# some other code which doesn't let you use a list comprehension
Ответ 4

Изменение каждого элемента во время итерации списка - это нормально, если вы не изменяете добавление / удаление элементов в список.

Вы можете использовать понимание списка:

l = ['a', ' list', 'of ', ' string ']
l = [item.strip() for item in l]

или просто выполните C-style цикл for:

for index, item in enumerate(l):
l[index] = item.strip()
python