【问题标题】:Python 3 : IndexError: list index out of range [duplicate]Python 3:IndexError:列表索引超出范围[重复]
【发布时间】:2016-07-24 05:52:00
【问题描述】:

我正在尝试从列表中删除重复项。我正在尝试使用以下代码来做到这一点。

>>> X
['a', 'b', 'c', 'd', 'e', 'f', 'a', 'b']
>>> for i in range(X_length) :
...  j=i+1
...  if X[i] == X[j] :
...   X.pop([j])

但我得到了

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
IndexError: list index out of range

请帮忙。

【问题讨论】:

  • 您的某些代码是否丢失? j 是什么?无论如何,我认为问题在于您正在缩短最后一个。当i 达到最大值时,列表不再那么长,因此您有索引错误。
  • 什么是 X_length 和 j?
  • X_length 是什么? j 是什么? X.pop([j]) 应该是什么?
  • 在迭代对象时不要修改它。 range(X_length)pop 之后太久。
  • 此问题与TigerhawkT3 标记的问题不重复。它们都涉及 IndexExceptions,但是此代码中存在不同的问题,这些问题尚未在任何答案中解决,并且无法通过其他线程解决。这是在浪费机会教初学者 Python 的工作原理。

标签: python


【解决方案1】:

当您开始从列表中删除项目时,它的大小会发生变化。因此,在某些删除之后,ith 索引可能不再存在:

>>> x = ['a', 'b', 'c', 'd', 'e']
>>> x[4]
'e'
>>> x.pop()
'e'
>>> x[4]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

删除重复项的更简单方法是将列表转换为 set,它只能包含唯一项。如果您必须将其作为列表,您可以将其转换回列表:list(set(X))。但是,这里没有保留顺序。


如果要删除连续重复项,请考虑使用新数组来存储 not 重复项:
unique_x = []
for i in range(len(x) - 1):
    if x[i] != x[i+1]:
        unique_x.append(x[i])
unique_x.append(x[-1])

请注意,我们的范围界限是len(x) - 1,否则我们会在使用x[i+1] 时超出数组界限。

【讨论】:

  • 输入列表的id是什么['a', 'b', 'c', 'd', 'e', 'f', 'a', 'b', 'a', 'a']?输出应该是['a', 'b', 'c', 'd', 'e', 'f', 'a', 'b', 'a'] 对吧?
  • @SilentMonk 是的,只要您将最后一个值附加到新列表中。
【解决方案2】:

@Rushy 的回答很棒,可能是我会推荐的。

也就是说,如果您想删除连续的重复项并且想要就地(通过修改列表而不是创建第二个列表)来完成,一种常见的技术是按照您的方式工作向后浏览列表:

def remove_consecutive_duplicates(lst):
    for i in range(len(lst) - 1, 1, -1):
        if lst[i] == lst[i-1]:
            lst.pop(i)

x = ['a', 'b', 'b', 'c', 'd', 'd', 'd', 'e', 'f', 'f']
remove_consecutive_duplicates(x)
print(x) # ['a', 'b', 'c', 'd', 'e', 'f']

通过从列表末尾开始并向后移动,您可以避免因缩短列表而超出列表末尾的问题。

例如如果您从 'aabc' 开始并向前移动,您将使用索引 0、1、2 和 3。

0
|
aabc

(Found a duplicate, so remove that element.)

 1
 |
abc

  2
  |
abc

   3
   |
abc  <-- Error! You ran off the end of the list.

向后看,您将使用索引 3、2、1 和 0:

   3
   |
aabc

  2
  |
aabc

 1
 |
aabc

(Found a duplicate so remove that element.)

0
|
abc <-- No problem here!

【讨论】:

    【解决方案3】:

    在列表的最后一次迭代中,j 的值将设置为 i + 1,在这种情况下,这将是长度或 8。然后您尝试访问X[j],但j 超出了列表的末尾。

    相反,只需将列表转换为集合:

    >>> set(X)
    {'e', 'f', 'd', 'c', 'a', 'b'}
    

    除非您需要保持秩序,在这种情况下,您需要在别处寻找ordered set

    【讨论】:

      【解决方案4】:

      一般不建议在迭代时改变序列,因为序列会不断变化。以下是一些其他方法:

      给定:

      X = ['a', 'b', 'c', 'd', 'e', 'f', 'a', 'b']
      

      如果您只对从列表中删除重复项感兴趣(并且顺序无关紧要),您可以使用集合:

      list(set(X))
      ['a', 'c', 'b', 'e', 'd', 'f']
      

      如果您想保持顺序并删除列表中任何位置的重复项,您可以在创建新列表时进行迭代:

      X_new = []
      for i in X:
          if i not in X_new:
              X_new.append(i)
      
      X_new
      # Out: ['a', 'b', 'c', 'd', 'e', 'f']
      

      如果您想删除连续重复项,请考虑@smarx 的回答。

      【讨论】:

        猜你喜欢
        • 2023-04-11
        • 1970-01-01
        • 2018-03-19
        • 2015-01-28
        • 1970-01-01
        • 2016-08-25
        • 2017-04-05
        • 2012-07-15
        • 2013-06-04
        相关资源
        最近更新 更多