2

Python for loop isn't iterating '0' from a list!

I tried to make a code to separate an input into numbers and letters(or operators):

g='10+10+20x'

t=[]
for each_g in g:
    t.append(each_g)

lol=[]
a=[]
for each_t in t:
    if each_t.isdigit():
        lol.append(each_t)
        x = t.index(each_t)
        t.pop(x)
    else:
        lol = ''.join(lol)
        a.append(lol)
        a.append(each_t)
        lol=[]
print(a)

The desired output would be:

['10', '+', '10', '+', '20', 'x']

but it prints

['1', '+', '1', '+', '2', 'x']

instead.

Is there any problems whit the code or a better solution to make it work as expected?

Thanks.

3 Answers 3

8

Don't modify a sequence that you're iterating over. Each pop is shifting a character down before you can process it.

In this case since you're not using t when you're done, there's no need for the pop at all - it's redundant.

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

Comments

3

Here's an alternative approach (as your code already has been thoroughly discussed by others):

In [38]: import re

In [39]: g='10+10+20x'

In [40]: re.findall('(\d+|[a-zA-Z]+|\+)',g)
Out[40]: ['10', '+', '10', '+', '20', 'x']

5 Comments

Well, that gave me a good idea of what regex can do, i'll consider using it, but as i'm new i find it a little difficult. Thanks!
re.findall('(\d+|\D+)',g) works well handling digits followed by non-digits. I'd thought that re.findall('(\d+)(\D+)',g) would be more useful in that it gave you a tuple of (number, operator) but it's not what the OP wanted.
@sotapme -- you are right, but as OP doesn't have much experience with regex, i think the current is probably more verbose.
What if i have something like '10+10+20lol' and want the 'lol' as['l', 'o', 'l'], i tried looking at docs.python.org/3.2/library/re.html but i couldn't find something.
@fenrirsoul -- just lose one + like '(\d+|[a-zA-Z]|\+)'
1

Editing a list (or any other iterable) while you're iterating over it is a horrible idea.

Here's how iterating over a list works:

when you say for each_t in t, what's actually happening is that a sequence of numbers is generated in turn; first 0, then 1 and so forth, all the way up to len(t)-1. The iterator then gets the element at that index and assigns it to each_t.

When you pop from that list, you are eliminating an index. Therefore, what used to be at index 3 is now at index 2 (if you popped something at an index less than 3). Then what happens is that the iterator accesses the element at the next number. But since the elements have essentially shifted down an index, when the iterator asks for the element at index i, it means "give me the element that used to be at index i". Instead, what it gets is "the element currently at index i, which is indeed the element that used to be at index i+1".

This is exactly why you skip over elements when you delete from a list as you're iterating over it

1 Comment

Thanks for the explanation, I'm really new to python and I appreciate it.

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.