递归时如何使用“ for in range:”修复“ IndexError:列表索引超出范围”

时间:2019-09-06 19:32:10

标签: python-3.x recursion

我正在尝试实现“ unique_in_order”功能。此函数将序列作为参数,并返回不包含具有相同值的任何元素且彼此相邻并保留元素原始顺序的项目列表。

 例如:

unique_in_order('AAAABBBCCDAABBB') == ['A', 'B', 'C', 'D', 'A', 'B']
unique_in_order('ABBCcAD')         == ['A', 'B', 'C', 'c', 'A', 'D']
unique_in_order([1,2,2,3,3])       == [1,2,3]
ets

此函数的代码:

def unique_in_order(iterable):
    iterable = list(iterable)
    l_lenth = int(len(iterable))
    for i in range(0, l_lenth-1):
        if iterable[i] == iterable[i+1]:
            del iterable[i+1]
            l_lenth = l_lenth - 1
            unique_in_order(iterable)
    return(iterable)`

但是,如果我们要运行它,则会发生错误:

    Traceback (most recent call last):
      File "test.py", line 15, in <module>
        unique_in_order(x)
      File "test.py", line 11, in unique_in_order
        unique_in_order(iterable)
      File "test.py", line 11, in unique_in_order
        unique_in_order(iterable)
      File "test.py", line 11, in unique_in_order
        unique_in_order(iterable)
      [Previous line repeated 4 more times]
      File "test.py", line 6, in unique_in_order
        if iterable[i] == iterable[i+1]:
    IndexError: list index out of range

我试图添加一些'print()'来监视进度:

def unique_in_order(iterable):
    iterable = list(iterable)
    l_lenth = int(len(iterable))
    for i in range(0, l_lenth-1):
        if iterable[i] == iterable[i+1]:
            del iterable[i+1]
            l_lenth = l_lenth - 1
            print('sign {0} was deleted \n new list: \n{1}'.format(i+1, iterable))
            print('new lenth: {0}, i = {1}'.format(l_lenth,i))
            unique_in_order(iterable)
    print('Result: {}'.format(iterable))
x = 'AAABBBCCDAA'
print('input data: {0}\nlenth: {1}'.format(x,len(x)))
unique_in_order(x)

结果:

input data: AAABBBCCDAA
lenth: 11
sign 1 was deleted
 new list:
['A', 'A', 'B', 'B', 'B', 'C', 'C', 'D', 'A', 'A']
new lenth: 10, i = 0
sign 1 was deleted
 new list:
['A', 'B', 'B', 'B', 'C', 'C', 'D', 'A', 'A']
new lenth: 9, i = 0
sign 2 was deleted
 new list:
['A', 'B', 'B', 'C', 'C', 'D', 'A', 'A']
new lenth: 8, i = 1
sign 2 was deleted
 new list:
['A', 'B', 'C', 'C', 'D', 'A', 'A']
new lenth: 7, i = 1
sign 3 was deleted
 new list:
['A', 'B', 'C', 'D', 'A', 'A']
new lenth: 6, i = 2
sign 5 was deleted
 new list:
['A', 'B', 'C', 'D', 'A']
new lenth: 5, i = 4
Result: ['A', 'B', 'C', 'D', 'A']
Result: ['A', 'B', 'C', 'D', 'A']
sign 5 was deleted
 new list:
['A', 'B', 'C', 'D', 'A']
new lenth: 5, i = 4
Result: ['A', 'B', 'C', 'D', 'A']
Traceback (most recent call last):
  File "test.py", line 16, in <module>
    unique_in_order(x)
  File "test.py", line 11, in unique_in_order
    unique_in_order(iterable)
  File "test.py", line 11, in unique_in_order
    unique_in_order(iterable)
  File "test.py", line 11, in unique_in_order
    unique_in_order(iterable)
  [Previous line repeated 1 more time]
  File "test.py", line 6, in unique_in_order
    if iterable[i] == iterable[i+1]:
IndexError: list index out of range

因此,正如我们所看到的,结果是正确的,但是由于出现'IndexError',所以我无法返回()输出数据。此外,当i = 4时,“结果:”行会显示两次以上(我想在此步骤中会发生此问题)。如果您能帮助我解决这个问题,我将不胜感激。预先感谢。

2 个答案:

答案 0 :(得分:1)

在遍历列表时,您将遇到一些古怪的行为,试图从列表中删除。而且我不明白为什么您要递归调用此函数,您已经在循环遍历整个列表了。这可以简单得多

def unique_in_order(iterable):
  iterable = list(iterable)
  result = [iterable[0]]
  for i in range(1, (len(iterable))-1):
    if result[len(result)-1] != iterable[i]:
      result.append(iterable[i])
  return(result)

如果您真的想要在没有结果列表的情况下执行此操作,则也许您有一些疯狂的内存约束,请使用while循环而不是for循环。 for循环的退出条件参数在循环开始时计算一次(在这种情况下为列表的长度),但是while循环的条件在每次迭代时都会计算。

答案 1 :(得分:0)

问题是您要遍历可迭代对象的原始长度。从列表中删除项目时,将其缩短。我可以看到您尝试通过从l_length中减去一个来处理此问题,但这没有任何作用,因为您已经将for循环使用的可迭代项初始化为range(0, l_lenth-1)。此后更改l_lenth不会有任何区别。您应该使用while循环代替while i<l_lenth