Python 3索引错误

时间:2016-10-14 05:43:37

标签: python list python-3.5 anagram

请考虑以下代码:

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()

在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形成的方式。此代码用于表示形成一对单词的字谜所需的步数。

3 个答案:

答案 0 :(得分:3)

在某些情况下,当您在迭代时缩短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变得足够大以超出它的容器范围之前终止。

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

你的第二次尝试只是因为&#34;匹配&#34;只在最后一个元素5中找到,因此当你改变列表lst时,它是在最后一次迭代期间并且没有效果。

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

一般来说,在迭代它时不会改变你的列表。而不是:

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

&#39; idiom&#39;,您应该选择:

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

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