Python列表清单为什么会出现此错误:IndexError:列表索引超出范围?

时间:2020-03-31 19:17:16

标签: python list

我做了一个应该删除列表列表中任何类似事件的函数,但我对以下错误感到惊讶:IndexError:列表索引超出范围,为什么会这样?

例如:

 input: [['a0', 'a3'], ['a1', 'a2'], ['a0', 'a3'], ['a2', 'a1'], ['a3', 'a1']]
 expected output:[['a0', 'a3'], ['a1', 'a2'], ['a3', 'a1']]
def getList(a):
    b=a
    lena = len(a)
    print(len(a))
    for i in range(lena):

        for j in range (i+1,lena):
            print(i,j)
            print(a[i],a[j])

            if(a[i][0],a[i][1])==(a[j][1],a[j][0]) or (a[i][0],a[i][1])==(a[j][0],a[j][1]):

                print(a)

a = [['a0', 'a3'], ['a1', 'a2'], ['a0','a3'], ['a2','a1'], ['a3', 'a1']]
getList(a)

输出:

[['a0', 'a3'], ['a1', 'a2'], ['a0', 'a3'], ['a2', 'a1'], ['a3', 'a1']]
5
0 1
['a0', 'a3'] ['a1', 'a2']
0 2
['a0', 'a3'] ['a0', 'a3']
[['a0', 'a3'], ['a1', 'a2'], ['a0', 'a3'], ['a2', 'a1'], ['a3', 'a1']]
0 3
['a0', 'a3'] ['a2', 'a1']
0 4
['a0', 'a3'] ['a3', 'a1']
1 2
['a1', 'a2'] ['a0', 'a3']
1 3
['a1', 'a2'] ['a2', 'a1']
[['a0', 'a3'], ['a1', 'a2'], ['a0', 'a3'], ['a2', 'a1'], ['a3', 'a1']]
1 4
['a1', 'a2'] ['a3', 'a1']
2 3
['a0', 'a3'] ['a2', 'a1']
2 4
['a0', 'a3'] ['a3', 'a1']
3 4
['a2', 'a1'] ['a3', 'a1']

当我通过添加b.pop(j)或诸如此类的任何东西来修改代码时:

def getList(a):
    b=a
    lena = len(a)
    print(len(a))
    for i in range(lena):

        for j in range (i+1,lena):
            print(i,j)
            print(a[i],a[j])

            if(a[i][0],a[i][1])==(a[j][1],a[j][0]) or (a[i][0],a[i][1])==(a[j][0],a[j][1]):

                print(a)
                b.pop(j)

a = [['a0', 'a3'], ['a1', 'a2'], ['a0','a3'], ['a2','a1'], ['a3', 'a1']]
getList(a)

结果:

    5
0 1
['a0', 'a3'] ['a1', 'a2']
0 2
['a0', 'a3'] ['a0', 'a3']
[['a0', 'a3'], ['a1', 'a2'], ['a0', 'a3'], ['a2', 'a1'], ['a3', 'a1']]
0 3
['a0', 'a3'] ['a3', 'a1']
0 4
Traceback (most recent call last):
  File "C:/Users/I/Desktop/papers/test.py", line 21, in <module>
    getList(a)
  File "C:/Users/I/Desktop/papers/test.py", line 13, in getList
    print(a[i],a[j])
IndexError: list index out of range

我想知道可能是什么问题?

2 个答案:

答案 0 :(得分:1)

在迭代列表时处理列表是灾难的根源,并且几乎总是可以避免的,方法是将结果累加到一个单独的结构上,或者至少为迭代目的复制原始列表(b = a别名,而不是副本,可以使用a.copy()a[:]完成)。 pop时,列表长度发生变化,并且迭代器引用不存在的列表元素。

此外,最好不要将打印与程序输出混淆。大多数算法的结果都不应为标准输出。相反,应将结果写入数据结构,并返回给调用者,以供调用者根据需要使用或转储。

另一个问题是效率:嵌套循环意味着O(n 2 )运行时间。使用多余的空间可以为您提供线性算法。

如果将每个子列表转换为元组,则它们将成为可散列的,并且可以将数据粘贴到set中以消除重复项,然后将所有内容转换回列表:

>>> [list(x) for x in set(tuple(sorted(x)) for x in a)]
[['a1', 'a2'], ['a1', 'a3'], ['a0', 'a3']]

问题是订单丢失。如果应该保留顺序,则可以使用一组作为查找表:

>>> lookup = set()
>>> result = []
>>> for pair in a:
...     key = tuple(sorted(pair))
...     if key not in lookup:
...         lookup.add(key)
...         result.append(pair)
...
>>> result
[['a0', 'a3'], ['a1', 'a2'], ['a3', 'a1']]

如果您使用的是CPython 3.6+,则可以利用dictionary ordering来改进上面显示的set方法:

>>> [list(x) for x in dict([tuple(sorted(x)), None] for x in a)]
[['a0', 'a3'], ['a1', 'a2'], ['a1', 'a3']]

3.6之前的版本可以使用collections.OrderedDict获得相同的结果:

>>> from collections import OrderedDict
>>> [list(x) for x in OrderedDict([tuple(sorted(x)), None] for x in a)]
[['a0', 'a3'], ['a1', 'a2'], ['a1', 'a3']]

答案 1 :(得分:1)

如果您调用b = a.copy()并返回b,则您的代码可以正常工作。 b = a表示变量名b指向与a相同的Object(list)。