Python: удаление элемента списка при итерации по списку [дубликат]



этот вопрос уже есть ответ здесь:



Я перебираю список элементов в Python, делаю некоторые действия над ним, а затем удаляю их, если они соответствуют определенным критериям.



for element in somelist:
do_action(element)
if check(element):
remove_element_from_list


что я должен использовать вместо remove_element?
У меня есть видел подобные вопросы, но заметил наличие части do_action, которая должна быть выполнена для всех элементов и, таким образом, исключает решение с помощью фильтров.

593   9  

9 ответов:

вы всегда можете перебирать копию списка, оставляя вам возможность изменять оригинал:

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.Х.

обновление: если вы хотите повторить вперед, это возможно, просто сложнее и уродливее:

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

список комп:

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)

вы можете расширить функцию, чтобы вызвать фильтр в условии.

Comments

    Ничего не найдено.