Programming Noob
Programming Noob

Reputation: 1845

How can you change the value of the iterating variable in a loop in Python?

I have something like this :

#tokens is a list of a few words
for i in xrange(0,len(tokens)):
    #some code to modify the contents of token[i]
    if tokens[i] == some value:
        del tokens[i]

Now if the array has 7 elements, i goes from 0 to 6, and in the middle of the processing if I delete an array element, then the new size becomes 6 but the loop will still run till i=6 and access tokens[6] and throw an error because the new size is 6 i.e. max index is 5.

I guess I can use a while loop with some condition like:

while(i<currMaxIndex)

where I can dynamically change currMaxIndex.

But I was just really curious to know if there was any way to alter i in the for loop itself.

If absolutely MUST know, this is my code:

for i in xrange(0,len(tokens)):
            tokens[i]=tokens[i].translate(string.maketrans("",""),string.punctuation)
            if tokens[i]=='':
                del tokens[i]

Upvotes: 4

Views: 188

Answers (2)

defuz
defuz

Reputation: 27591

I would do this:

def myfilter(token):
    return token.translate(None, string.punctuation)   

tokens = filter(None, map(myfilter, tokens))

If the logic is too complicated to do it through the map / filter, it is recommended to use this approach:

for item in items[:]: # [:] copies the list
    if condition(item):
        items.remove(item)

Upvotes: 4

Blender
Blender

Reputation: 298106

len(tokens) is computed when you create the xrange object, so if you are deleting elements from the list, tokens[i] may not exist or may have a value that is different from what you'd expect.

For example:

>>> a = [1, 2, 3]
>>> a[1]
2
>>> del a[1]
>>> a[1]
3

Instead of modifying the original list, create a new one:

new_tokens = []

for token in tokens:
    translated = token.translate(None, string.punctuation)

    if translated:
        new_tokens.append(translated)

Or you can filter a generator expression:

new_tokens = filter(None, (token.translate(None, string.punctuation) for token in tokens))

Upvotes: 2

Related Questions