比较列表中的数字时出现索引错误

时间:2020-05-31 03:47:59

标签: python python-3.x indexing

我正在尝试构建一个函数,该函数提供给定的列表或数字字符串(对于字符串,数字用“,”分隔),目标数字查找最后一个可以到达目标的值的数量。只有吃掉一个等于或小于自己的数字,数字才能增加1,吃掉较小的数字后,较小的数字将从列表中删除。每个号码列表都会重置为原始号码。我已经接近了,但是我一直收到索引错误,而且不确定如何解决

def cannibal(l, target):

    newl = l
    count = 0
    i = 0
    listlen = len(newl)

    try:
        newl = l.split(",")
        newl.sort(reverse = True)
        newl = list(map(int, newl)) 
        print (newl)

    except:
        newl.sort(reverse = True)
        print (newl)

    finally:
        while i < len(newl):

            print ("index is ",i)

            if newl[i] == target:
                print ("match found at ", i)
                count += 1
                i += 1
                continue

            if newl[i] > target:
                i += 1
                continue

            for j in range(i+1,listlen-1):

                print ("list length is",listlen)
                while newl[i] > newl [j] and j<listlen:  

                    print (newl[i]," is eating ",newl[i+1])
                    newl.remove(newl [i+1])
                    newl[i] = newl[i]+1
                    listlen = len(newl)
                    print (newl)

                    if newl[i] == target:
                        print ("match found at ", i)
                        count += 1
                        i += 1
                        break
            i += 1


        print (count)
        return count

给出cannibal([27, 9, 3, 8, 11], 50)后,它将返回IndexError: list index out of range并指向while newl[i] > newl [j] and j<listlen:

1 个答案:

答案 0 :(得分:2)

>>> cannibal([27, 9, 3, 8, 11], 50)
[27, 11, 9, 8, 3]
index is  0
list length is 5
27  is eating  11
[28, 9, 8, 3]
28  is eating  9
[29, 8, 3]
29  is eating  8
[30, 3]
30  is eating  3
[31]
Traceback (most recent call last):
  File "<pyshell#169>", line 1, in <module>
    cannibal([27, 9, 3, 8, 11], 50)
  File "<pyshell#168>", line 36, in cannibal
    while newl[i] > newl [j] and j<listlen:
IndexError: list index out of range

我运行了您提到的失败的测试用例。乍一看,似乎存在不适当的退出条件。经过进一步检查,似乎您的最里面的while循环最终被迫评估会引发IndexError的条件。

当我在while循环的末尾插入print(newl, i, j)时,我们会得到以下结果:

>>> cannibal([27, 9, 3, 8, 11], 50)
[27, 11, 9, 8, 3]
index is  0
list length is 5
27  is eating  11
[28, 9, 8, 3]
[28, 9, 8, 3] 0 1
28  is eating  9
[29, 8, 3]
[29, 8, 3] 0 1
29  is eating  8
[30, 3]
[30, 3] 0 1
30  is eating  3
[31]
[31] 0 1
Traceback (most recent call last):
  File "<pyshell#175>", line 1, in <module>
    cannibal([27, 9, 3, 8, 11], 50)
  File "<pyshell#174>", line 37, in cannibal
    while newl[i] > newl [j] and j<listlen:
IndexError: list index out of range

希望现在清楚了问题所在。

在while循环中的某个时刻,您最终得到newl = [31]i = 0j = 1

计算条件while newl[i] > newl [j] and j<listlen时,当然newl[0] > newl[1]会中断功能,因为newl[1]不存在。

要阻止发生 的错误,最简单的方法是添加一个标志以退出for循环。

def cannibal(l, target):

    newl = l
    count = 0
    i = 0
    listlen = len(newl)

    try:
        newl = l.split(",")
        newl.sort(reverse = True)
        newl = list(map(int, newl)) 
        print (newl)

    except:
        newl.sort(reverse = True)
        print (newl)

    finally:
        while i < len(newl):

            print ("index is ",i)

            if newl[i] == target:
                print ("match found at ", i)
                count += 1
                i += 1
                continue

            if newl[i] > target:
                i += 1
                continue

            break_out = False

            for j in range(i+1,listlen-1):

                if break_out: break

                print ("list length is",listlen)

                while newl[i] > newl [j] and j<listlen:  

                    print (newl[i]," is eating ",newl[i+1])
                    newl.remove(newl [i+1])
                    newl[i] = newl[i]+1
                    listlen = len(newl)
                    print (newl)
                    print(newl, i, j)
                    if newl[i] == target:
                        print ("match found at ", i)
                        count += 1
                        i += 1
                        print(newl, i, j)
                        break
                    if i >= len(newl) or j >= len(newl):
                        print ("loop is broken")
                        break_out = True
                        break
            i += 1


        print (count)
        return count

但是,我相信问题会更加严重。我不完全了解您打算如何使用此功能,但我有种直觉,您不希望newl在for循环的第一次迭代之后永久成为[31]