一、原因
讲这个是因为很多初学者在遇到for循环和列表结合去处理问题的时候,往往会出现代码书写是没有问题的,但是就是无法执行正确答案,出现逻辑错误。但是找来找去就是不知道问题出在哪,实际上就是列表内部元素处理的问题。
给大家举个例子:
比如有一个简单的自然数构成的序列
[1, 2, 3, 4, 5, 6, 7, 8]
我有一个问题,要使用for循环和列表相关的知识点,将列表当中的奇数删除,留下偶数
好,那这样的话我就可以这么处理,先使用
for循环
遍历整个列表,在循环体中去判断,如果遍历到的元素
跟2取余不等于0
,那么就说这个数字是奇数,那在此条件下列表使用
remove
的方法删除具体元素
num = [1, 2, 3, 4, 5, 6, 7, 8]
for ele in num:
if ele % 2 != 0:
num.remove(ele)
print(num)
运行结果如下:
看上去好像是没问题的是吗?
如果大家觉得这就没问题了,那就掉陷阱里面了,如果我把序列改成整个样子
[1, 2, 3, 4, 5, 6, 7, 9]
那么,按照我们刚才的思路,还能只得出偶数吗?不用犹豫,既然我提出了这个问题,那肯定是不会只有偶数了,我们看结果
那么问题就来了,表面上看上去程序是没问题的啊,为什么我就修改了一个数据,结果就出问题了呢,听我慢慢道来
二、详细解释具体原因
我们来详细进入循环体中看看到底是怎么一回事
1、
从下标为
0
的第一个元素开始,数字
1
是奇数,OK,程序做删除,但是删除之后,由于我们操作的是原列表,那么,删除1之后,后面的2,3,4,5,6,7,9这些元素的下标会统一减一
[1, 2, 3, 4, 5, 6, 7, 9]
[2, 3, 4, 5, 6, 7, 9]
那么此时,下标为0的元素就是2了,那么程序会认为,下标为0这个位置的元素已经遍历过,所以不对2进行判断,虽然2恰巧不是奇数,继续向下
2、
遍历到下标为
1
的元素时,
3
是奇数,好,删除
[2, 3, 4, 5, 6, 7, 9]
[2, 4, 5, 6, 7, 9]
那么此时下标为1的元素就变成了数字4,恰好它不是奇数,继续向后
3
、当程序遍历到下标为
2
的元素的时候,
5
是奇数,进行删除,此时下标为2的元素是6
[2, 4, 5, 6, 7, 9]
[2, 4, 6, 7, 9]
4、
继续向后,遍历到下标为
3
,下标为3的元素是
7
,是奇数,进行删除
[2, 4, 6, 7, 9]
[2, 4, 6, 9]
5、
此时下标为
3
的元素是
9
,但是程序认为已经遍历过了,不做处理,所以最后结果就是
[2, 4, 6, 9]
那真的是这样吗?我们把2,4,6分别替换成奇数,看看会不会不做处理
[1,11,3,13,5,15,7,9]
事实证明,确实如此,好,那既然知道了问题所在,那应该怎么解决呢?既然在从左向右依次遍历列表元素时,如果删除某个元素,那么后面还没有被遍历的元素下标势必会变动。那么我们就不从左向右了,
从右向左逆序
怎么样?
ok ,那就利用列表当中的切片操作,逆序遍历
完美解决问题,那么文章开头的那一组数据也就正常了
三、题外话
问题虽然解决了,但是代码还是多,俗话说人生苦短,我用python,能一行解决岂不更好
来一个
列表推导式
,直接把想要提取的数据直接拿出来,干脆,直截了当
有关列表推导式的知识点,小伙伴可以自行查找,不难理解