16

Basically, I need a way to return control to the beginning of a for loop and actually restart the entire iteration process after taking an action if a certain condition is met.

What I'm trying to do is this:

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

That way, if ['berry','||','||','||','pancake] is inside the list, I'll wind up with:

['berry','||','pancake'] instead.

Thanks!

6
  • Are you asking about nested loops? while something: for ...? If so, what's so complex? Please post a code sample to show what you're doing. Commented Sep 13, 2010 at 22:41
  • Can you provide some sample code so we can figure out what you're asking. "continue" works for both "for" and "while" loops. It looks like you want something different. Commented Sep 13, 2010 at 22:43
  • 5
    continue does not do this for while loops it merely skips the rest of the loop body, just as it does with for loops. Try rephrasing your question to describe what you're trying to accomplish instead of how you're trying to accomplish it Commented Sep 13, 2010 at 22:43
  • Yeah, I really have to wonder why you're trying to do this. Perhaps there's a better solution, if you look at the big picture. Commented Sep 13, 2010 at 22:47
  • Thanks guys. I've edited the original post with a code sample that explains what I'm trying to do! Commented Sep 13, 2010 at 22:48

8 Answers 8

44

I'm not sure what you mean by "restarting". Do you want to start iterating over from the beginning, or simply skip the current iteration?

If it's the latter, then for loops support continue just like while loops do:

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

The above will print the numbers from 0 to 9, except for 5.

If you're talking about starting over from the beginning of the for loop, there's no way to do that except "manually", for example by wrapping it in a while loop:

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

The above will print the numbers from 0 to 5, then start over from 0 again, and so on indefinitely (not really a great example, I know).

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a hell of a lot! The second solution is brilliant.
No problem. Also have a look at Nathon's answer, it has a cleaner/simpler version of this using for's else clause.
Haha that second example smells like C++ so bad
27
while True:
    for i in xrange(10):
        if condition(i):
            break
    else:
        break

That will do what you seem to want. Why you would want to do it is a different matter. Maybe you should take a look at your code and make sure you're not missing an obvious and easier way to do it.

2 Comments

As clarification (since for: ... else: can be kind of confusing and this also has breaks in two nested loops): if the condition is true, it breaks out of the for loop, which means it skips the else part of that loop, which means it goes back to the top of the while loop. If the condition is always false, it completes the for loop, goes into the else part, and breaks from the while loop.
Thanks, this is what I was looking for. It's very clean, but a bit unintuitive that you cloud write this in python.
5

some action that resarts the whole process

A poor way to think of an algorithm.

You're just filtering, i.e., removing duplicates.

And -- in Python -- you're happiest making copies, not trying to do del. In general, there's very little call to use 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'] ) )

Comments

4

The inevitable itertools version, because it just came to me:

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'])]

1 Comment

+1, I would have just returned a generator expression though
3

Continue will work for any loop.

2 Comments

But I'm looking for a way to restart the for loop entirely...control goes back to the state it was in at the beginning.
3

continue works in for loops also.

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

1 Comment

Thanks--that's good to know! But I'm looking for a way to restart the for loop entirely...control goes back to the state it was in at the beginning.
1

As you can see answering your question leads to some rather convoluted code. Usually a better way can be found, which is why such constructs aren't built into the language

If you are not comfortable using itertools, consider using this loop instead. Not only is it easier to follow than your restarting for loop, it is also more efficient because it doesn't waste time rechecking items that have already been passed over.

L = ['berry','||','||','||','pancake']
idx=1
while idx<len(L):
    if L[idx-1]==L[idx]:
        del L[idx]
    else:
        idx+=1

Comments

0
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']
"""

And by the way this is repeating of Remove adjacent duplicate elements from a list

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.