Python 3 索引错误

Python 3 Index Error

考虑以下代码:

def anadist(string1, string2):
    string1_list = []
    string2_list = []

    for i in range(len(string1)):
        string1_list.append(string1[i])
    for i in range(len(string2)):
        string2_list.append(string2[i])

    # Test returns for checking
    # return (string1_list,string2_list)
    # return len(string1_list)
    # return len(string2_list)

    for i in range(0,len(string1_list)):
        try:
            if (string1_list[i]) in string2_list:
                com = string1_list.pop(i)
                com_index = string2_list.index(com)
                string2_list.pop(com_index)
            else:
                pass
        except ValueError:
            pass
    return string1_list


def main():
    str1 = input("Enter string #1 >>> ")
    str2 = input("Enter string #2 >>> ")
    result = anadist(str1, str2)
    print(result)

#Boilerplate Check
if __name__ == "__main__":
    main()

运行 in Python 3.5.2 引发 IndexError:

Traceback (most recent call last):
  File "E:\CSE107L\Practice\anadist.py", line 34, in <module>
    main()
  File "E:\CSE107L\Practice\anadist.py", line 29, in main
    result = anadist(str1, str2)
  File "E:\CSE107L\Practice\anadist.py", line 15, in anadist
    if (string1_list[i]) in string2_list:
IndexError: list index out of range

而且我找不到问题所在。我写了另一个类似的代码并且有效:

def main():
    lst = [1,2,3,4,5]
    lst2 = [5,6,7,8,9]
    for i in range(len(lst)):
        if lst[i] in lst2:
            com = lst.pop(i)
            lst2_index = lst2.index(com)
            lst2.pop(lst2_index)
        else:
            pass
    print(lst)

if __name__ == "__main__":
    main()

我觉得错误来自于我形成的方式string1_list。此代码表示形成一对单词的字谜需要多少步。

在某些情况下,您在迭代时会缩短 string_list1

if (string1_list[i]) in string2_list:
    com = string1_list.pop(i)  # string1_list gets shorter here

但是,您的 range 没有改变。它仍然会从 0 开始计算到 原始 长度 string1_list(不包括)。这将导致 IndexError 任何时候 string1_list.pop(i) 被调用。

一种可能的解决方案是使用 while 循环代替:

i = 0
while i < len(string1_list):
    try:
        if string1_list[i] in string2_list:
            com = string1_list.pop(i)
            com_index = string2_list.index(com)
            string2_list.pop(com_index)
        else:
            pass
    except ValueError:
        pass
    i += 1

这将导致在每次迭代后检查循环终止条件。如果您从 string1_list 中删除一些元素,它仍然可以,因为循环将在 i 变得足够大以超出其容器的边界之前终止。

您的问题是您正在通过执行 string1_list.pop(i)for 循环中改变 string1_list。通过执行 string1_list.pop(i),在 for 循环中减少了列表的长度,但您仍在迭代原始列表的长度。

你的第二批代码之所以有效,是因为你在循环的最后一次迭代中只 pop

您的第二次尝试之所以成功,是因为 "match" 仅在最后一个元素 5 中找到,因此当您改变列表 lst 时,它是在 最后一次迭代,没有效果。

您第一次尝试的问题是您可能会从列表的开头删除。计数器不会更新,并且在某些时候可能会达到列表中不再存在的值(它已被弹出)。在输入中没有匹配项的情况下尝试运行它,看看它是否有效。

一般来说,不要在遍历列表时改变列表。而不是:

for i in range(len(lst)):
    # mutate list

'idiom',您应该选择:

for i in list(list_object):   # or for i in list_object[:]:

它首先制作一个副本,并允许您通过保持变异和循环分开来变异原始 list_object