Ответ 1
Вы всегда можете перебирать копию списка, оставляя за собой право изменять оригинал:
for item in list(somelist):
...
somelist.remove(item)
Я повторяю список элементов в Python, делаю на нем какое-то действие, а затем удаляю их, если они удовлетворяют определенным критериям.
for element in somelist:
do_action(element)
if check(element):
remove_element_from_list
Что следует использовать вместо remove_element? Я видел похожие вопросы, но обратите внимание на наличие части do_action, которая должна быть выполнена для всех элементов и, таким образом, устраняет решение использования фильтров.
Вы всегда можете перебирать копию списка, оставляя за собой право изменять оригинал:
for item in list(somelist):
...
somelist.remove(item)
Чтобы выполнить эти критерии: измените исходный список на месте, нет экземпляров списка, только один проход, работает, традиционное решение состоит в повторении итерации назад:
for i in xrange(len(somelist) - 1, -1, -1):
element = somelist[i]
do_action(element)
if check(element):
del somelist[i]
Бонус: не выполняет len(somelist)
на каждой итерации. Работает на любой версии Python (по крайней мере, еще в 1.5.2)... s/xrange/range/for 3.X.
Обновление: если вы хотите итерации вперед, это возможно, просто сложнее и уродливее:
i = 0
n = len(somelist)
while i < n:
element = somelist[i]
do_action(element)
if check(element):
del somelist[i]
n = n - 1
else:
i = i + 1
Список comp:
results = [x for x in (do_action(element) for element in somelist) if check(element)]
for element in somelist:
do_action(element)
somelist[:] = (x for x in somelist if not check(x))
Если вам действительно нужно сделать это за один проход без копирования списка
i=0
while i < len(somelist):
element = somelist[i]
do_action(element)
if check(element):
del somelist[i]
else:
i+=1
Вы все равно можете использовать фильтр, переходя к внешней функции, модификацию элемента (итерация только один раз)
def do_the_magic(x):
do_action(x)
return check(x)
# you can get a different filtered list
filter(do_the_magic,yourList)
# or have it modified in place (as suggested by Steven Rumbalski, see comment)
yourList[:] = itertools.ifilter(do_the_magic, yourList)
Другой способ сделать это:
while i<len(your_list):
if #condition :
del your_list[i]
else:
i+=1
Итак, вы удаляете элементы бок о бок, проверяя
Вы можете создать генератор, который возвращает все, что не удалено:
def newlist(somelist):
for element in somelist:
do_action(element)
if not check(element):
yield element
Почему бы не переписать его как
for element in somelist:
do_action(element)
if check(element):
remove_element_from_list
Посмотрите на этот вопрос, как удалить из списка, хотя похоже, что вы уже видели, что Удалить элементы из списка во время итерации
Другой вариант - сделать это, если вы действительно хотите сохранить это же
newlist = []
for element in somelist:
do_action(element)
if not check(element):
newlst.append(element)
Не совсем на месте, но есть идея сделать это:
a = ['a', 'b']
def inplace(a):
c = []
while len(a) > 0:
e = a.pop(0)
if e == 'b':
c.append(e)
a.extend(c)
Вы можете расширить функцию, чтобы вызвать фильтр в состоянии.