一、列表删除的特许情况
Python的列表删除有时候你会发现他的好玩,
如果你不熟悉C语言的话,我相信,
你的python列表删除某些元素时,他会输出你没有想到的新列表。
不是所有的列表删除都可以用remov()
废话少说,直接上代码,代码会比一切更有说服力。
首先,我们要把列表里面我们不需要的杂质去掉,我想你绝对会想到列表的
remove()方法,这的确是个好方法。这种内置函数即简单又好用。
x = [1, 2, 1, 2, 1, 2, 1, 2, 1]
for i in x:
if i == 1:
x.remove(i)
print(x) # 输出[2,2,2,2]
我们发现这串代码读起来是那么一回事,输出结果也是正确的。
但是整个代码下来,他的逻辑是错误的。
如果我们把上述代码稍作改变
x = [1, 2, 1, 2, 1, 1, 1]
for i in x:
if i == 1:
x.remove(i)
print(x) # 输出[2,2,1]
此时输出的结果就并非我们想要的了,还有一个一没有移除。
具体解析
其实这只是Python的一个特性而已:
python会自动对列表内存进行收缩并移动列表元素以保证所元素之间没有空隙,
增加列表元素时也会自动扩展内存并对元素进行移动以保证元素之间没有空隙。
其实说白了就是你如果删除其中元素他后面的元素就会往前补进一位,
其他元素也会跟随其后。
所以我们要了解这段代码为什么会输出[2,2,1],还是要把这段代码可视化,清楚明确才是我这篇文章的目的。
我们不妨先为这段代码插个桩,让我们可以知道每次循环
x = [1, 2, 1, 2, 1, 1, 1]
for i in x:
i # i就是这个桩
if i == 1:
x.remove(i)
print(x) # 输出[2,2,1]
(删除前):
(删除后,1后面的元素都不断的替补被删除的位置,并且进入第二次循环图):
你一定很好奇,为什么删除第一个一后,那个箭头会指向1,而不是指向第一个2;
假设我们为这些元素加上一些好理解的数组概念呢,假设他们有索引呢?
看下面这个:
(第一次循环,删除前,下标为索引):
(第二次循环,删除前,下标为索引):
根据索引循环的话我们就好理解很多了,你可以理解成就是索引为0时已经循环过了,机器就进行索引为1的循环,逐一循环下去,而不会在乎你索引相对的值是否有变化。
逐步看下去:
(第三次循环)
索引2的元素’2’向前挺进一位变成了索引1,而其他也逐一的进行变化。
再观:
可见,最后输出
所以最终输出的列表为什么是[2,2,1]你现在也大概懂了,
那接下我就开始讲让他可以输出[2,2]的代码了。
二、Python具体操作方法
切片
切片是第一种方法,但是我们首先要了解切片是个什么东西
切片:[start: stop :step]
start:第一个数字表示切片开始的位置(默认为0);
stop:第二个数字表示切片截止(但不包含)位置(默认列表长度);
step:切片步长,可省略;
alist = [1, 2, 3, 4, 5, 6]
print(alist[::])
# 输出[1,2,3,4,5,6]
看到这我想你应该明白了怎么改那个代码了;
我们在循环体中的x加上切片,代码循环的时候就是直接按照切片的规矩一步步来,话不多说,上代码
x = [1, 2, 1, 2, 1, 1, 1]
for i in x[::]:
i # 设置断点看i值你就会懂我下面那句话了
if i == 1:
x.remove(i)
print(x) # 输出[2,2]
每次删除后,x更新。而切片[::]限制了刚刚上面那个箭头指向下一个的元素,让他老老实实的从第一位依次进行循环。
但是切片方法并不是最优解,差了点有意思,
既然都看到这了,不如看看下面这个"从后向前",
我觉得这个肯定让你眼前一亮!
从后向前
为什么从后向前删除列表中不想要的元素呢?
你如果有仔细看前面我说的那个python列表的一个特性,你就知道了;
我们从后先前删除元素呢就是避免了这个特性,让上面那组图片中的箭头
逐一按位进行下去,也避免了后面的元素占用了前面的元素位置,
造成的(假设的假设的!)索引没变,值变了的那种情况
x = [1, 2, 1, 2, 1, 1, 1]
for i in range(len(x) - 1, -1, -1):
i #i =6,5,4,3,2,1
if x[i] == 1:
del x[i]
print(x) # 输出[2,2]
python列表问题就暂且到这了,后续如其他博主看出这篇还有问题告知我一下我会逐一进行更改,并且注明。
(若转载请注明出处,谢谢!)