【问题标题】:Why does Python throw IndexError for array insertion problem?为什么 Python 会为数组插入问题抛出 IndexError?
【发布时间】:2021-08-04 22:19:58
【问题描述】:

我正在研究 python 中的数据结构,并且遇到了数组操作。目前我正在考虑插入。

为了练习,我必须做的问题是“如果数组中的元素为零,则将右边的元素也设为零”。看起来很简单,我以为我明白了,但是我抛出了一个 IndexError,我对为什么感到困惑。这里是:

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

根据我的想法,arr[i + 1] 在这种情况下是4,我的意思是让它等于零。但我收到错误"IndexError: list assignment index out of range"。对我来说这没有意义,因为arr[i + 1] 仍在范围内,所以这里发生了什么?我已经把它分解并做了一些测试代码,看看它是否不同,否则没关系:

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

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

有人可以解释一下区别吗?

【问题讨论】:

  • 当 a[i] == (数组中的最后一个元素) 并且没有找到 a[i+1] 时抛出异常。尝试使用 range(len(a) - 1)
  • 是的,行得通!现在拍我的额头。我只是明白为什么当你打字的时候。谢谢@Namandeep_Kaur
  • 具体来说,在循环中将4 更改为0,然后在下一次传递中使用that 0 并尝试找到右侧的元素
  • 它恰好在第二个示例中有效,因为 if 仅在最后一个索引 - 1 处触发,因此 i+1 有效。但是如果你厌倦了a = [1, 3, 2] 它也会失败
  • 注意,你的方法的问题是,如果你有类似[1,0,2,3,1,0] 的东西,当你修复一个错误时,它会导致[1, 0,0,0,0,0]....

标签: python indexing index-error


【解决方案1】:

您的循环遍历列表。到达最后一个元素时抛出错误。您的代码尝试将下一个设为 0:arr[i + 1] = 0。如果您的列表是[1, 2, 0],当它到达第一个0 时,它将尝试编辑索引3 处的第四项。您可以通过多种方式解决此问题。

在抛出错误之前检查:

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) 会找到长度,只有当项目不是最后一个时,编辑才会起作用。你也可以在之前退出它,使用一些更简洁的代码:

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

第二种方法是尝试捕获错误,但我不推荐此解决方案。

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

而且代码更简洁:

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

这确保它只有在由于相同的错误时才能正常进行。如果有另一个错误,它将被抛出并正常打印。 如果你愿意,你可以把它放在不同的位置,你可以灵活地选择你希望代码如何运行/查看并找到相同的结果。

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

或者可能:

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

第三种方法是在循环到达最后一个之前运行循环。

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

    return arr

如果您不知道,pass 通常用作将在其他时间编写的代码的占位符。我不建议像这样使用 pass,它看起来很乱,并且可能会导致程序运行速度变慢。尝试使用条件语句或先编辑循环。

【讨论】:

  • 我认为第三个是最干净的。 EAFP 在这里并不真正适用。您不必在每一步检查i 是否是有效索引;你知道 range(len(arr)-1) 是函数应该做的正确范围。
猜你喜欢
  • 2019-11-10
  • 2021-12-20
  • 2021-03-05
  • 2021-03-19
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2014-02-05
  • 2021-04-09
相关资源
最近更新 更多