Skip to main content
 首页 » 编程设计

python之使用索引列表从另一个列表中删除给我索引超出范围错误之为什么

2025年05月04日20开发

我正在比较两个列表并在匹配时删除第一个重复实例,然后继续。我知道这些列表之间有很多重复项,所以我不能只使用列表理解或类似的东西,因为我需要查看哪一侧有更多实例,我基本上只是设置从两个列表中减去共享元素。

这是我的代码:

toDelFromrbIndex = [] 
toDelFromabIndex = [] 
for rbIndex, (barcode, timestamp, prepack, workorder) in enumerate(restoredBottles): 
    for abIndex, (idx, bcode, tstamp, tableName) in enumerate(allBottles): 
         if barcode==bcode and timestamp == tstamp: 
             #Remove from both lists 
             toDelFromrbIndex.append(rbIndex) 
             toDelFromabIndex.append(abIndex) 
 
 for index in toDelFromrbIndex: 
     del restoredBottles[index] 
 
 for index in toDelFromabIndex: 
     del allBottles[index] 

在此之前,我将它们删除到“toDelFromrbIdnex.append(rbIndex)”所在的位置,并意识到这会扰乱我的迭代,可能会跳过项目。所以我先存储索引,然后再从两个列表中将它们全部删除。

但是,这个 for index in toDelFromrbIdnex: del restoredBottles[index] 给我一个 index out of range 错误,为什么?

请您参考如下方法:

您正在从小到大删除索引。每次删除都会将已删除索引右侧的元素向下移动一级,因此索引 N 移动到 N - 1。

最后,您尝试删除的最后一个索引现在可能指向列表之外。以下也会抛出一个 IndexError:

foo = [17, 42] 
for index in (0, 1): 
    del foo[index] 

因为首先我们删除了索引 0 处的 17。删除第一个元素意味着 42 将成为索引 0 处的元素,并且索引 1 处不再有任何内容。

您需要首先删除最高索引,因此反向处理您的索引:

 for index in reversed(toDelFromrbIdnex): 
     del restoredBottles[index] 
 
 for index in sorted(toDelFromabIdnex, reverse=True): 
     del allBottles[index] 

我对 toDelFromabIndnex 进行了排序,因为您最终可以按任意顺序向其中添加 ID。

另外请注意:您目前匹配“瓶子”的效率非常低。您正在使用嵌套循环,因此对于 N 个 restoredBottles 条目和 M 个 allBottles 您正在进行 O(NM) 测试。随着任一列表的增长,您将以二次方式增加运行时间。例如,对于 N = 100 和 M = 1000,您进行 100,000 次比较,对于 N = 200,则变为 200,000 次比较,或者将 M 更改为 5000,您需要进行 500,000 次比较。

如果您使用中间字典,您可以将其减少到 O(N + M) 步:

# mapping from barcode and timestamp, to index in restoredBottles 
bcts_idx = {} 
for i, (bc, ts, *_) in enumerate(restoredBottles) 
    bcts_idx.setdefault((bc, ts), []).append(i) 
 
toDelFromrbIndex = [] 
toDelFromabIndex = [] 
for abIndex, (idx, bcode, tstamp, tableName) in enumerate(allBottles): 
    for rbIndex in bcts_idx.get((bcode, tstamp), ()): 
        # Remove from both lists 
        toDelFromrbIndex.append(rbIndex) 
        toDelFromabIndex.append(abIndex)