【问题标题】:Why I have IndexError when program makes succesful first step?为什么程序成功第一步时出现 IndexError?
【发布时间】:2026-02-04 05:05:01
【问题描述】:

我尝试制作排序器,删除第一个列表中 IP 的重复项并将其保存到文件中,但在第一轮成功后,它给了我 IndexError: list index out of range。

我期待正常的排序过程,但它不起作用

代码:

ip1 = open('hosts', 'r')
ip2 = open('rotten', 'r')
ipList1 = [line.strip().split('\n') for line in ip1]
ipList2 = [line.strip().split('\n') for line in ip2]
for i in range(len(ipList1)):
    for a in range(len(ipList2)):
        if(ipList1[i] == ipList2[a]):
            print('match')
            del(ipList1[i])
            del(ipList2[a])
            i -= 1
            a -= 1
c = open('end', 'w')
for d in range(len(ipList1)):
    c.write(str(ipList1[d]) + '\n')
c.close()

【问题讨论】:

  • 你的'for'循环不是pythonic和过于复杂。在 Python 中,您只需遍历元素,如果您确实需要索引,请使用 'for idx, element in enumerate(iterable):'

标签: python python-3.x list sorting


【解决方案1】:

您在迭代列表时从列表中删除,这就是您收到 IndexError 的原因。

使用sets 可以更轻松地完成此操作:

with open('hosts') as ip1, open('rotten') as ip2:
    ipList1 = set(line.strip().split('\n') for line in ip1)
    ipList2 = set(line.strip().split('\n') for line in ip2)

good = ipList1 - ipList2

with open('end', 'w') as c:
    for d in good:
        c.write(d + '\n')

【讨论】:

  • sets 在这里不起作用,因为line.strip().split() 将返回一个无法散列的列表(尽管这可能是一个错误 - 为什么 OP 从文件,然后在换行符上拆分它们?)
【解决方案2】:

您迅速更改了列表。例如,表达式获取一个长度为 5 个元素的列表,在第一次迭代后删除 4 个,因此在第二次迭代中尝试提取第二个元素,但现在它不存在。
如有必要保存排序,您可以使用生成器表达式:

ips = [ip for ip in ipList1 if ip not in set(list2)]

如果没有,则使用集合表达式。

【讨论】:

    【解决方案3】:

    您不应该修改当前正在迭代的列表。 解决方法是制作第三个列表来保存非重复项。另一种方法是只使用集合并将它们彼此相减,尽管我知道您是否喜欢一个列表本身中的重复项。此外,您现在的操作方式只有在同一索引处才能找到重复项。

    ip2 = open('rotten', 'r')
    ipList1 = [line.strip().replace('\n', '') for line in ip1]
    ipList2 = [line.strip().replace('\n', '') for line in ip2]
    ip1.close()
    ip2.close()
    newlist = []
    for v in ip1:
        if v not in ip2:
            newlist.append(v)
    
    c = open('end', 'w')
    c.write('\n'.join(newlist))
    c.close()
    

    【讨论】:

      【解决方案4】:

      其他答案侧重于在迭代容器时从容器中删除。虽然这通常是一个坏主意,但这并不是问题的症结所在,因为您已经(非pythonically)设置了for 循环以使用一系列索引,因此严格来说,您并没有在列表本身上进行迭代。

      不,这里的问题是 i-=1a-=1 没有效果:当 for 循环开始新的迭代时,它不能脱离索引的先前值。它只是从您在开始时建立的迭代器中获取它总是注定要获取的下一个值(在您的情况下,range() 的输出)

      【讨论】:

        最近更新 更多