Home > other >  Is it possible to skip a fixed number of iterations in a loop in Python?
Is it possible to skip a fixed number of iterations in a loop in Python?

Time:12-20

Introduction:

So I know that there is already a question (Skip multiple iterations in loop) similar to mine with a really good answer, but there are still some open questions for me:


Question 1:

Is there any way of doing it without an iterator?

I am looking for something like * 3:
song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']

for sing in song:
    print(sing, end=" ")
    if sing == 'look':
        continue * 3

expected output:

always look side of life 

Question 2:

If I have to use an iterator object, then is it possible to do it a fixed amount of time?

The original question has a solution like this:

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
song_iter = iter(song)
for sing in song_iter:
    print(sing)
    if sing == 'look':

        next(song_iter)
        next(song_iter)
        next(song_iter)

        print(next(song_iter))

But I want it to do it let's say x = 5 times. It is not possible like this:

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
song_iter = iter(song)
for sing in song_iter:
    print(sing)
    if sing == 'look':

        next(song_iter) * x

        print(next(song_iter))

So how would you do it? I know it is possible to use the function itertools.islice, but is there a way without any libraries?


My Approach:

This works great:

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
song_iter = iter(song)

skip_iterations = 3

for sing in song_iter:
    print(sing)
    if sing == "look":
        while skip_iterations > 0:
            next(song_iter, "")

            skip_iterations -= 1

Output:

always look side of life 

But maybe anyone else has a better idea? :)


Links:

The Question I was mentioning - The Answer for that question

CodePudding user response:

Ans 1 There are many ways to do the problem one of the easiest one would be by checking the index like

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
skip_iterations=3
for i,sing in enumerate(song):
    if not song.index('look') < i < song.index('look') skip_iterations 1:
    print(sing, end=" ")

'enumerate' returns (index, element) Ans 2 Your method is just fine you may prefer a for loop instead of while loop but thats just a personal suggestion.

CodePudding user response:

An alternate approach is to have a C style for loop that has more complete update logic:

def cfor(i, test_i, update_i):
    while test_i(i):
        yield i
        i=update_i(i)

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']

skip=3

for i in cfor(0, 
              lambda i: i<len(song), 
              lambda i: i skip 1 if song[i]=='look' else i 1):
    print(song[i], end=' ')

Or, that can just be a while loop:

idx=0
while(idx<len(song)):
    print(song[idx], end=' ')
    idx =skip 1 if song[idx]=='look' else 1

If your skip is large, either of these would be faster.


You can also use enumerate with a comprehension:

l=song.index('look')
' '.join([w for i,w in enumerate(song) if i<=l or i>(l skip)])

CodePudding user response:

With a skip counter:

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']

skip = 0
for sing in song:
    if skip:
        skip -= 1
        continue
    print(sing, end=" ")
    if sing == 'look':
        skip = 3

CodePudding user response:

Question 1

You could employ the use of an iteration bound to keep track of when you can resume evaluation in the loop

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']

iter_bound = -1
for i, sing in enumerate(song):
    if i <= iter_bound:
        continue
    if sing == 'look':
        iter_bound = i   3
    print(sing, end=" ")

If you use this very often in your code, you may want to code a function around it:

from typing import Iterable, Callable

def skip_n_on_condition(iterator: Iterable, condition: Callable, n_skips: int):
    """Loop over iterable and perform n_skips whenever the condition on the element is met"""
    iter_bound = -1
    for i, element in enumerate(iterator):
        if i <= iter_bound:
            continue
        if condition(element):
            iter_bound = i   3
        yield element
    
song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']

print(*skip_n_on_condition(song, lambda x: x == 'look', 3), end=" ")

Question 2

Since you know the number of times you will be looping, it may be better to use a for loop. It will also be an implementation that does not change the value of skip_iterations which you may not have expected.

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
song_iter = iter(song)

skip_iterations = 3

for sing in song_iter:
    print(sing)
    if sing == "look":
        for _ in range(skip_iterations):
            next(song_iter, "")

You could make the loop a one liner using a list comprehension.

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']
song_iter = iter(song)

skip_iterations = 3

for sing in song_iter:
    print(sing)
    if sing == "look":
        [next(song_iter, "") for _ in range(skip_iterations)]

CodePudding user response:

I would consider the "historic" way of iterating.

song = ['always', 'look', 'on', 'the', 'bright', 'side', 'of', 'life']

i = 0
while i < len(song):
    sing = song[i]
    i  = 1

    print(sing, end=" ")
    if sing == 'look':
        i  = 3
        continue

    # ... other code ...
  • Related