2

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

4
  • 2
    your approach seems good enough, except I would use a for loop: for _ in range(skip_iterations): next(song_iter) Commented Dec 19, 2021 at 16:49
  • 1
    Every for loop uses an iterator, whether you're aware of it or not. Using iter simply gives you access to one at the code level. Anyway, it seems like your question is: given an iterator object, how can we call next on it a specified number of times? Well - how do you normally do anything a specified number of times in Python? With... a for loop, right? So.... Commented Dec 19, 2021 at 16:49
  • "If I have to use an iterator object, then is it possible to do it a fixed amount of time?" - with an arbitrary iterator, no. Iterators are sequential, not random-access. For example, an iterator over a linked list cannot be advanced without following links one by one, and a generator doesn't even have well-defined elements until you run it and make it yield elements one by one. Commented Dec 19, 2021 at 16:52
  • If you're just iterating over a list, then you can skip in constant time easily enough, but not with a standard list iterator. You would have to write your own handling. Commented Dec 19, 2021 at 16:59

5 Answers 5

1

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.

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

Comments

1

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

Comments

0

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

Comments

0

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.