Python skip next index in loop without next(iterator) possible?

I’m writing a program i Python where I want a for loop to skip the next index in a list if certain conditions are met, I do however want to access the current and next item to do some computations in these cases i.e. myList[i] and myList[i+1] so I don’t want to iterate to the next object as that would force me to create numerous variables to access prev-object for computations. If I wrote this in Java or C I would use i++ while pythons i+=1 still iterates the item I want to skip.

# this works
itr = iter(range(len(myList)))
for i in itr:
	print(i)
	if i == 5:
		next(itr)
	

# but not this, it still loops with i = 6
for i in range(len(myList))
	print(i)
	if i == 5:
		i+=1

I suppose I’m upset because it requires itr = iter(range(len(myList))) and that seems so out of place to me, am I missing something?

I think you’re iterating i=6 because your for loop is setup as if a foreach loop.
Dunno if it applies in python, i’ve never written a python program in my life, but in most, if not all other languages, your syntax says, “do this for all indexes in the array”
so even if you say i+1, the loop still just continues to index 6, and attempts the same operations.
Where as the first example uses a iterator(e.g. a simple counter), and you tell the iterator to increment +1
in java id written it like this.

someArray=someOtherVaribale
for (i = 0; i < someArray.Length; i++)
{
if(i == 5)
i=i+1
}

1 Like

you could use a while loop to replicate for loop


yes I did this on my phone, in vim, coz i am crazy

2 Likes
for i in range(len(myList)):
    if i == 6:
        continue

    print(i)
2 Likes

this was my first idea, but from what I gathered he needs i before continue.

oh you incremented the skip index, I see. nice

Continue works great for the example but I need to skip iterations that are not known to me ahead of time so I would have to use some flag like skip_next == true and check for that at the beginning of the loop which doesn’t really make the code shorter or more elegant.

1 Like

@radek Your suggestion probably makes most sense here, It let’s thinks remain integer :slight_smile:

Your initial code is the way to go then in my opinion. The only thing I’d change is to use enumerate instead of iterating over the list’s length.

2 Likes

I’m totally with you on the Java example, that’s why it confuses the hell out of me that I can’t do the same in the python for-loop. Instead I have to resort to a while-loop and declare the variable outside of it but I like my variables to go out of scope and stuff :stuck_out_tongue:

it is because i is not the index of the array but the content of the index in the array, so you are adding +1 to what ever is in the index, and not the pointer.

lets say you have a array containing car brands.
so
cars[] array = {“toyota”, “volvo”, “bmw”}

and you attempt the same on index 3.
(again im not a master of python, but since youre not getting a segfault im guessing this is what happens).

if(i==3)

This statement would never be true since i would be either toyota, volvo, or bmw.
doesn’t python support the good’ol type of counting for loops? else just add your own counter like
i=0
for x in y

some meta code …

i++

1 Like

Yeah, your absolutely right about the foreach behavior. I just expected there to be some option where I have an integer that I can change to jump index in a for loop but that does not seem to be the case and I would have to use while instead. Oh well…

pretty much what @pFtpr said; enumerate gets you where you need to go, and remember you can use continue in a for loop. Also, I find it clearer to use a dedicated skip variable, though it does become more verbose.

myList, skip = list(range(10)), False
for i, item in enumerate(myList):
   print(i)
   if skip:
       print('skipping')
       skip = False
       continue
   skip = (i == 5)

Can you kill the index for your code? Or if you really want to cut lines (possibly at a performance hit), zip a generator for skipping.

myList = list(range(10))
for skip, item in zip(((i == 5) for i in range(len(myList))), myList):
    if skip:
        continue

Actually, do you mind sharing more about what you’re trying to do? You can also use filter to do something like

filtered = filter(lambda i: (i - 1) != 5, range(len(myList)))
for i, item in zip(filtered, myList):
    print(i)

but again you’re using range(len(myList)) when you may not need an index at all

1 Like

myList is a list of objects, sometimes the objects in the list have to be handled in pairs and sometimes not, this is known based on the type attribute, I mean it works, I’m just flabbergasted that there is no way to iterate in a for loop by simple arithmetic (i+=1)

itr = iter(range(len(myList)))
for i in itr:
	if(myList[i].type == type1)
	        otherList.append(various calculations based on data from myList[i])
        elif(myList[i].type == type2)
                otherList.append(calclations on myList[i] and myList[i+1])
		next(itr) # to not iterate over myList[i+1]


Idiomatic python is largely focused on removing redundancy, so next(myList) will both advance the iterator as well as return the next object. Now, obviously, whatever you find most maintainable for your team is what you should do- but the pythonic way of looping would remove the indices and deal directly with item.

otherList = []
myList = iter(range(10))
for item in myList:
    print(item)
    if not item % 2: # arbitrary comparison
        otherList.append(item)
    elif item == 5: # more type checking or whatever
        # item returns 5 and next(myList) returns 6
        otherList.extend((item, next(myList)))
        # on the next loop, item is 7

Also, note that

myList = range(10)
for item in iter(myList):
    ...

will throw a TypeError, while the previous example does work.

And perhaps I should explain if it wasn’t clear that myList can indeed be a list of objects. I used range(10) as a quick example but any list can be made into an iterator without calling len()

But I’m not appending the item to otherList, I’m using it’s attributes to compute something else so would I be able to access the attributes from the previous object once I go to next(myList)? I suppose I could create a temp object prevmyList = myList[i] and then next(myList), is that the pythonic way for handling this problem?

itr = iter(range(len(myList)))
for i in itr:
	if(myList[i].type == type1)
	        otherList.append(obj.box(myList[i].length, myList[i].wdith, myList[i].height, myList[i].length*myList[i].width&height))
        elif(myList[i].type == type2)
                otherList.append(obj.box(myList[i].length + myList[i+1].length, ...))

yes

myList = iter(range(10))
for item in myList:
    print(f'before:\t{item}')
    if item == 5:
        nextObject = next(myList) # advance and return 6
        print(f'skipping {nextObject}')
        # item is still 5
    print(f'after:\t{item}')
before:	0
after:	0
before:	1
after:	1
before:	2
after:	2
before:	3
after:	3
before:	4
after:	4
before:	5
skipping 6
after:	5
before:	7
after:	7
before:	8
after:	8
before:	9
after:	9

really no need, just keep using item and call next(myList) as many times as you want

myList = iter(range(20))
for item in myList:
    print(item)
    if item == 5:
        nextObject = next(myList) # advance and return 6
        print(f'skipping {nextObject}')
        # item is still 5
    elif item == 12:
        for _ in range(6): # skip the next 6 items
            print(f'skipping {next(myList)}')
            print(f'item is still {item}')
0
1
2
3
4
5
skipping 6
7
8
9
10
11
12
skipping 13
item is still 12
skipping 14
item is still 12
skipping 15
item is still 12
skipping 16
item is still 12
skipping 17
item is still 12
skipping 18
item is still 12
19
object example because why not
import attr

@attr.s
class Example:
    specialAttr = attr.ib()

myList = iter(Example(i) for i in range(20))
for item in myList:
    print(item.specialAttr)
    if not item.specialAttr:
        print(type(item)) # print type on first loop
    elif item.specialAttr == 5:
        nextObject = next(myList) # advance and return 6
        print(f'skipping {nextObject.specialAttr}')
        # item is still 5
    elif item.specialAttr == 12:
        for _ in range(6): # skip the next 6 items
            print(f'skipping {next(myList).specialAttr}')
            print(f'item attr is still {item.specialAttr}')
0
<class '__main__.Example'>
1
2
3
4
5
skipping 6
7
8
9
10
11
12
skipping 13
item attr is still 12
skipping 14
item attr is still 12
skipping 15
item attr is still 12
skipping 16
item attr is still 12
skipping 17
item attr is still 12
skipping 18
item attr is still 12
19
1 Like

That’s insightful, thanks! Once I get the math part right I’ll clean up the code using your advice :slight_smile:

1 Like