Как правильно изменить итератор цикла в Python из цикла - PullRequest
9 голосов
/ 17 декабря 2011

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

Так, например, скажем, что

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

Я в основном хочу написать (в принципе, а не фактический код, который я пытаюсь реализовать)

Если элементом списка является 'b' или 'c', удалите его из списка и возьмите следующий.

Но

for s in list:
    if s=='b' or s=='c':
        list.remove(s)

терпит неудачу, потому что при удалении «b» цикл принимает «d», а не «c» в качестве следующего элемента.Так есть ли способ сделать это быстрее, чем хранить элементы в отдельном списке и впоследствии удалять их?

Спасибо.

Ответы [ 4 ]

10 голосов
/ 17 декабря 2011

Более простой способ - использовать копию списка - это можно сделать с помощью среза, который продолжается от «начала» до «конца» списка, например:

for s in list[:]:
    if s=='b' or s=='c':
        list.remove(s)

Вы рассмотрели это, и это достаточно просто, чтобы быть в вашем коде, если этот список не очень большой, и в критической части кода (например, в основном цикле игры-действия). В этом случае я иногда использую следующую идиому:

to_remove = []
for index, s in enumerate(list):
    if s == "b" or s == "c":
         to_remove.append(index)

for index in reversed(to_remove):
    del list[index]

Конечно, вместо этого вы можете прибегнуть к циклу while:

index = 0
while index < len(list):
   if s == "b" or s == "c":
       del list[index]
       continue
   index += 1
8 голосов
/ 17 декабря 2011

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

filter(lambda x:x not in ['b','c'],['a','b','c','d','e'])

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

[x for x in ['a','b','c','d','e'] if x not in ['b','c']]
3 голосов
/ 05 августа 2013

Это именно то, для чего предназначен itertools.ifilter.

from itertools import ifilter

ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e'])

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

list(ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e']))

или

[x for x in ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e'])]
1 голос
/ 17 декабря 2011

Если вы в порядке с созданием копии списка, вы можете сделать это следующим образом ( понимание списка ):

[s for s in list if s != 'b' and s != 'c']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...