简体   繁体   中英

Why does Python throw IndexError for array insertion problem?

I'm going through data structures in python and I've come across array operations. At the moment I'm looking at insertion.

For practice, the problem I have to do is "If zero is in the array, make the element to the right zero also". Seems pretty simple and I thought I got it however, my throws an IndexError and I'm confused on why. Here it is:

def duplicateZeroes(arr):
    for i in range(len(arr)):
        if arr[i] == 0:
            arr[i + 1] = 0

    return arr


print(duplicateZeroes([1, 2, 3, 0, 4]))

>>> arr[i + 1] = 0
IndexError: list assignment index out of range

From my thinking, arr[i + 1] in this case is 4 , and I'm saying make it equal to zero. But I get the error "IndexError: list assignment index out of range" . To me this doesn't make sense because arr[i + 1] is still in range so what is happening here? I've broken it down and done some test code to see if it's different but it's fine otherwise:

a = [1, 2, 3]
for i in range(len(a)):
    if a[i] == 2:
        a[i+1] = "changed"
print(a)

>>> [1, 2, 'changed']

Can someone please explain the difference?

Your loop iterates through the lists. The error is thrown when it reaches the last element. Your code attempts to make the next one 0: arr[i + 1] = 0 . If you're list is [1, 2, 0] , when it reaches the first 0, it will try to edit the fourth item, at index 3 . You could solve this with multiple ways.

Checking before the error is thrown:

def duplicateZeroes(arr):
    for i in range(len(arr)):
        if arr[i] == 0 and not i == len(arr):
            arr[i + 1] = 0

    return arr

len(arr) will find the length, and the editing will only work when the item is not the last. You could exit it before as well, with some cleaner code:

def duplicateZeroes(arr):
    for i in range(len(arr)):
        if i == len(arr): return arr
        if arr[i] == 0:
            arr[i + 1] = 0
    return arr

A second way would be to try and catch the error, though I wouldn't recommend this solution.

def duplicateZeroes(arr):
    for i in range(len(arr)):
        if arr[i] == 0:
            try: arr[i + 1] = 0
            except: pass
    return arr

And in cleaner code:

def duplicateZeroes(arr):
    for i in range(len(arr)):
        if arr[i] == 0:
            try: arr[i + 1] = 0
            except IndexError: pass
    return arr

This makes sure that it only proceeds normally if it is due to the same error. If there is anothe error, it will be thrown and printed normally. If you wanted, you could place it in a different position, you have flexibility on how you want the code to run/look and finding the same result.

def duplicateZeroes(arr):
    try:
        for i in range(len(arr)):
            if arr[i] == 0:
                arr[i + 1] = 0
    except IndexError: pass
    return arr

Or possibly:

def duplicateZeroes(arr):
    for i in range(len(arr)):
        try:
            if arr[i] == 0:
                arr[i + 1] = 0
        except IndexError: pass
    return arr

A third would be to run the loop right before it reaches the last.

def duplicateZeroes(arr):
    for i in range(len(arr)-1):
        if arr[i] == 0:
            arr[i + 1] = 0

    return arr

In case you don't know, pass is usually used as a placeholder for code that will be written at another time. I wouldn't recommend using pass like this, it looks messy, and probably causes the program to run slower. Try using a conditional statement or editing the loop first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM