0

I have an initial list named vbn. I am thinking of a function that adds 0 after each 0 in the list.

So that vbn = [1,0,2,3,0,4,5,0] turns into vbn = [1,0,0,2,3,0,0,4,5,0,0].

I used a for loop and .insert() method to do so and obtained the result below.

vbn = [1,0,2,3,0,4,5,0]
s = 0
for i,j in enumerate(vbn[s:]):
    if j == 0:
        vbn.insert(i+1,0)
        s += i+2
print(vbn)

Outputs:

[1, 0, 0, 2, 3, 0, 0, 4, 0, 5, 0]

From what I have understood in my code, the s in my for loop statement is not affected by the iteration at all. s within the loop changes as expected though.

Can someone please explain why is that? And how I can solve the issue.

Thanks in advance!

4 Answers 4

3

Your problem is that the indexes at which you're inserting are no longer valid after the first insert, because you have increased the size of the list. If you change your code to insert x instead of 0, and print vbn in each iteration of the loop, you can see what is happening:

vbn = [1,0,2,3,0,4,5,0]
s = 0
for i,j in enumerate(vbn[s:]):
    if j == 0:
        vbn.insert(i+1,'x')
        s += i+2
    print(vbn)

Output:

[1, 0, 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 'x', 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 'x', 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 'x', 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 'x', 0, 4, 'x', 5, 0]

As you can see, even the second insertion occurs at the wrong place. You can work around this by adding an offset to the insertion point, and increasing that offset each time you make an insert:

vbn = [1,0,2,3,0,4,5,0]
s = 0
o = 1
for i,j in enumerate(vbn[s:]):
    if j == 0:
        vbn.insert(i+o,'x')
        s += i+2
        o += 1
    print(vbn)

Output (in this case you can see x being inserted in the places you expect):

[1, 0, 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 'x', 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 'x', 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 'x', 4, 5, 0]
[1, 0, 'x', 2, 3, 0, 'x', 4, 5, 0, 'x']

Just change the x back to a 0 to get your desired result. Note that I'm not sure what the s += i+2 code is for; I've left it in on the presumption you use it after the loop.

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

3 Comments

I believe the s += 2 was OP's attempt to change the index called in the loop, I was just about to comment that it doesn't do anything in the loop itself.
Please note, that python evaluates the statement of the for loop only once at the beginning of the loop, the changes in s therefore are not taken into account in the statement inside the for-loop conditions.
@LeoE absolutely, the code would not work at all otherwise. OP seems to understand that to be the case as well.
1

As an alternative method if you don't want to iterate multiple values is to create a new array in a loop:

vbn = [1,0,2,3,0,4,5,0]
new = []

for i in vbn:
    if i == 0:
        new += [i, 0]
    else:
        new += [i]
print(new)

5 Comments

This is nice and simple. You could even do it in one line: new = [t for x in [[v] if v != 0 else [v, 0] for v in vbn] for t in x]
Can you explain that? I couldn't figure out how to make it work on my own, and it isn't a very intuitive list comprehension looking at it.
If you just take the inner loop ([[v] if v != 0 else [v, 0] for v in vbn]), it creates a list of either an entry or an entry followed by a 0 if the entry is 0 (much like your loop) i.e. [[1], [0, 0], [2], [3], [0, 0], [4], [5], [0, 0]]. The outer two loops then flatten that list.
is the [t for x in * for t in x] just a python thing? I can break up the inner [[v] if v != 0 else [v, 0] for v in vbn] into a standard for loop, but the outer section is what throws me.
Yeah, if you search for python flatten list that's what you'll find (with >5000 upvotes!)
0

You can try to create a new list and insert the element (the non-zero number or two zeros) in vbn to the new list.

vbn = [1,0,2,3,0,4,5,0]
newlist = []
for i in vbn: 
    if i == 0: 
        newlist.insert(len(newlist),i)
        newlist.insert(len(newlist),0)
    else: 
        newlist.insert(len(newlist),i)   
print (newlist)

The displayed results is:

[1, 0, 0, 2, 3, 0, 0, 4, 5, 0, 0]

Comments

0

Although,I couldnt figure out the reason why the s in loop isnt iterating; i though noticed another problem in the code i.e. everytime you set value of s as s+(i+2) eg 0+(1+2), the other time its value is changes as 3+(i+2) in place of 0+(i+2)

Though i have an alternate solution for your question i.e.

vbn = [1,0,2,3,0,4,5,0]
s = 0
arr = []*10 #list to store no. of positions we need to add 0 
for i,j in enumerate(vbn):
  if j == 0:
    arr.append(i)
m=0 #variable to keep count of number of times the list is extended before the current one
for k in arr:
  k+=m #since, when we add zero to the list the current positions of elements changes
  vbn.insert(k+1,0)
  m+=1
print(vbn)

Comments

Your Answer

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