Python – способ перезапустить цикл for, аналогичный продолжению циклов while?

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

Я пытаюсь сделать следующее:

    for index, item in enumerate(list2):
    if item == '||' and list2[index-1] == '||':
        del list2[index]
        *<some action that resarts the whole process>*

Таким образом, если ['berry','||','||','||','pancake] находится внутри списка, я получу:

['ягода','||','блин'] вместо этого.

Спасибо!


person Georgina    schedule 13.09.2010    source источник
comment
Вы спрашиваете о вложенных циклах? while something: for ...? Если да, то что тут сложного? Пожалуйста, опубликуйте пример кода, чтобы показать, что вы делаете.   -  person S.Lott    schedule 14.09.2010
comment
Можете ли вы предоставить пример кода, чтобы мы могли понять, что вы просите. continue работает как для циклов for, так и для циклов while. Похоже, вы хотите чего-то другого.   -  person Aaron D    schedule 14.09.2010
comment
continue не делает этого для циклов while, он просто пропускает остальную часть тела цикла, как и в случае с циклами for. Попробуйте перефразировать свой вопрос, чтобы описать, чего вы пытаетесь достичь, а не как вы пытаетесь это сделать.   -  person Geoff Reedy    schedule 14.09.2010
comment
Да, мне действительно интересно, почему ты пытаешься это сделать. Возможно, есть лучшее решение, если вы посмотрите на общую картину.   -  person David Z    schedule 14.09.2010
comment
Спасибо, парни. Я отредактировал исходный пост с образцом кода, который объясняет, что я пытаюсь сделать!   -  person Georgina    schedule 14.09.2010
comment
Хотя THC4k не отвечает на вопрос, это хороший способ решить исходную проблему. Если вы настаиваете на удалении элементов из списка, вам лучше просто использовать один цикл while и самостоятельно управлять индексом.   -  person John La Rooy    schedule 14.09.2010


Ответы (8)


Я не уверен, что вы подразумеваете под «перезапуском». Вы хотите начать итерацию с самого начала или просто пропустить текущую итерацию?

Если последнее, то циклы for поддерживают continue точно так же, как циклы while:

for i in xrange(10):
  if i == 5:
    continue
  print i

Приведенное выше напечатает числа от 0 до 9, кроме 5.

Если вы говорите о том, чтобы начать сначала с начала цикла for, нет другого способа сделать это, кроме как «вручную», например, заключив его в цикл while:

should_restart = True
while should_restart:
  should_restart = False
  for i in xrange(10):
    print i
    if i == 5:
      should_restart = True
      break

Приведенное выше напечатает числа от 0 до 5, затем снова начнет с 0 и так далее до бесконечности (не очень хороший пример, я знаю).

person Liquid_Fire    schedule 13.09.2010
comment
Чертовски спасибо! Второе решение гениальное. - person Georgina; 14.09.2010
comment
Без проблем. Также взгляните на ответ Натона, у него есть более чистая/простая версия с использованием предложения for else. - person Liquid_Fire; 14.09.2010
comment
Ха-ха, второй пример так сильно пахнет C++ - person machine yearning; 10.08.2011

while True:
    for i in xrange(10):
        if condition(i):
            break
    else:
        break

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

person nmichaels    schedule 13.09.2010
comment
В качестве пояснения (поскольку for: ... else: может немного сбивать с толку, и в этом также есть breaks в двух вложенных циклах): если условие истинно, оно выходит из цикла for, что означает, что оно пропускает часть else этого цикла, что означает, что он идет вернуться к началу while петли. Если условие всегда ложно, оно завершает цикл for, переходит в часть else и breaks из цикла while. - person Vivian; 02.09.2016

какое-то действие, которое перезапускает весь процесс

Плохой способ думать об алгоритме.

Вы просто фильтруете, то есть удаляете дубликаты.

И — в Python — вам больше всего нравится делать копии, а не пытаться делать del. В общем, очень мало обращений к использованию del.

def unique( some_list ):
    list_iter= iter(some_list)
    prev= list_iter.next()
    for item in list_iter:
        if item != prev:
            yield prev
            prev= item
    yield prev

list( unique( ['berry','||','||','||','pancake'] ) )
person S.Lott    schedule 13.09.2010
comment
Чтобы было ясно, он удаляет соседние дубликаты. Кажется, это то, что делает ваш метод, но это не то, что обычно подразумевается под названием «уникальный». - person David M.; 14.09.2010
comment
@ Дэвид М.: Хотя это и правда, это своего рода негативный комментарий. уникальный не подходит. Хорошо. Что ты посоветуешь? Можете ли вы сделать положительный комментарий, который предлагает что-то? - person S.Lott; 14.09.2010
comment
Конечно, если вам нужна такая забота. (Что бы это ни стоило, я проголосовал за ваш ответ; я не пытаюсь вас разорвать, просто не хочу, чтобы ОП был сбит с толку.) В рецептах itertools это называется unique_justseen, возможно, unique_adjacent было бы лучше. - person David M.; 14.09.2010
comment
@David M: пытаюсь сломить тебя Что? Вы указали на возможную ошибку. Почему бы не сделать следующий логический шаг и не сделать предложение? Это не нянька — это подход к обеспечению ценности. Сказать что-то не то, что обычно подразумевается, имеет минимальную ценность. Улучшение ответа добавляет больше ценности. Указание на ошибку не добавляет ценности. Я не прошу нянчиться. Я прошу вас создать как можно больше ценности. Вы должны иметь некоторое представление. Поделись. - person S.Lott; 14.09.2010
comment
Прошу прощения, неправильно воспринял ваш комментарий. Вероятно, это из-за того, что меня окружают сотрудники отдела кадров. - person David M.; 14.09.2010

Неизбежная версия itertools, потому что она только что пришла мне в голову:

from itertools import groupby

def uniq(seq):
    for key, items in groupby(seq):
        yield key

print list(uniq(['berry','||','||','||','pancake'])) # ['berry','||', 'pancake']
# or simply:
print [key for key, items in groupby(['berry','||','||','||','pancake'])]
person Jochen Ritzel    schedule 13.09.2010
comment
+1, я бы просто вернул выражение генератора - person John La Rooy; 14.09.2010

Continue будет работать для любого цикла.

person volting    schedule 13.09.2010
comment
Но я ищу способ полностью перезапустить цикл for... управление возвращается в состояние, в котором оно было в начале. - person Georgina; 14.09.2010
comment
Хорошая ссылка для этого: en.wikibooks.org/wiki/Python_Programming/ - person Aaron D; 14.09.2010

continue также работает в циклах for.

>>> for i in range(3):
...     print 'Before', i
...     if i == 1:
...             continue
...     print 'After', i
... 
Before 0
After 0
Before 1
# After 1 is missing
Before 2
After 2
person Sam Dolan    schedule 13.09.2010
comment
Спасибо - это приятно знать! Но я ищу способ полностью перезапустить цикл for... управление возвращается в состояние, в котором оно было в начале. - person Georgina; 14.09.2010

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

Если вам неудобно использовать itertools, рассмотрите возможность использования этого цикла. Это не только проще, чем перезапуск цикла for, но и более эффективно, поскольку не тратится время на повторную проверку элементов, которые уже были пропущены.

L = ['berry','||','||','||','pancake']
idx=1
while idx<len(L):
    if L[idx-1]==L[idx]:
        del L[idx]
    else:
        idx+=1
person John La Rooy    schedule 13.09.2010

def remove_adjacent(nums):
     return [a for a,b in zip(nums, nums[1:]+[not nums[-1]]) if a != b]

example = ['berry','||','||','||','pancake']

example = remove_adjacent(example)
print example
""" Output:
['berry', '||', 'pancake']
"""

И, кстати, это повторение Удалить соседние повторяющиеся элементы из список

person Tony Veijalainen    schedule 13.09.2010