Python中使用list.insert按指定索引插入元素结果与预期不符的原因
结果差异的核心原因
出现输出和预期不符的本质,是对list.insert()的执行规则存在认知偏差:list.insert(index, obj)的作用逻辑是,在调用方法的瞬间,把目标元素obj插入到当前列表的index位置;插入完成后,原列表中位于该索引及之后的所有元素,会自动向后顺延一位。它并不是一个「提前锁定最终位置、等所有元素收集完成后再统一摆放到对应索引」的操作。
逐轮执行过程还原
我们顺着代码的运行顺序,记录每一步插入后列表c的状态:
- 第一次循环取到配对值
(number=2, letter='c'):此时c还是长度为0的空列表,执行c.insert(2, [2, 'c'])。按照Python语法规则,当insert传入的索引值大于等于当前列表长度时,元素会直接插入到列表末尾,这一步执行完,c的内容为[[2, 'c']] - 第二次循环取到配对值
(number=1, letter='b'):此时c的长度为1,要在索引1的位置插入元素,刚好对应列表末尾位置,插入完成后c的内容为[[2, 'c'], [1, 'b']] - 第三次循环取到配对值
(number=0, letter='a'):要在当前c的索引0位置插入元素,原列表中索引0、1位置的元素会整体向后顺延一位,插入完成后c的内容为[[0, 'a'], [2, 'c'], [1, 'b']],和你实际运行得到的输出完全一致。
预期逻辑和实际执行的本质差异
你预期得到结果的逻辑,本质是按索引定点填充固定长度的数组:不考虑插入顺序,最终每个元素都落在a列表值对应的固定索引位置上。但逐次调用insert的实现方式,每一次插入的索引参照物都是「当时列表里已经存在的元素排布」,不是预先设定好的最终固定坐标:
比如你最初想把带索引值2的元素放到目标列表的第2位,但此时列表还是空的,根本不存在前两个位置可以用来“预留空间”,直接插入就只能落在列表末尾;后续你插入索引1、0的元素时,这些在靠前位置执行的插入操作,会把之前已经插进去的元素往后挤压,最终所有元素的位置自然和你预想的固定坐标对不上。
达成预期结果的实现方式
如果要得到[[0, 'a'], [1, 'b'], [2, 'c']]的输出,不需要逐次动态插入,直接初始化固定长度的目标列表,通过索引赋值即可实现:
a = [2,1,0] b = ['c','b','a'] # 初始化和待插入元素数量一致的固定长度列表 c = [None] * len(a) for number, letter in zip(a, b): # 直接按索引值给对应位置赋值,不会出现元素移位挤压的问题 c[number] = [number, letter] print(c) # 运行输出:[[0, 'a'], [1, 'b'], [2, 'c']]
内容的提问来源于stack exchange,提问作者Matthew Komitsky
相关产品推荐
相关产品推荐

