在以下两个示例中,我尝试使用两种不同类型的循环从列表中删除负元素。
首先我尝试使用普通循环for i in list
,但在这种情况下,当我执行list1.remove(elm)
时,列表的大小减少一个元素。因此,在下一个循环中,第二个元素移动到第一个元素位置。因此,在下一个循环中测试if elm < 0
时会遗漏第二个元素。因此,它不会从列表中删除所有负面元素。
其次,我尝试使用切片。我从切片中理解的是它创建了一个临时列表。所以,当我for i in list2[:]
时,它会创建一个新的临时list2 = [-1,3,-2,-5,4,7,8]
,但我仍然没有得到清晰的图片,它是如何工作的。它删除了所有的负面因素。
#!/usr/env/bin
# remove all the negative value from the list.
list1 = [-1,3,-2,-5,4,7,8]
list2 = [-1,3,-2,-5,4,7,8]
# Looping through the list.
for elm in list1:
if elm < 0:
list1.remove(elm)
print 'list1: ', list1
# Looping through the list using slice.
for elm in list2[:]:
if elm < 0:
list2.remove(elm)
print 'list2: ', list2
Output:-python slice.py
list1: [3, -5, 4, 7, 8]
list2: [3, 4, 7, 8]
答案 0 :(得分:4)
问题是迭代列表并同时修改它会产生一些不好的结果。
例如,如果您在索引2处,并在那里删除负数,则索引3处的值将移至索引2.在下一次迭代中,您将转到索引3,但跳过旧值指数3(新指数2)。
切片会创建一个副本,因此即使删除底片也不会受到影响。
仅供参考,另一种可能性是
filter(lambda x: x >= 0, list2)
或
[x for x in list2 if x >= 0]
编辑:
以下是迭代。
(index) list1 elem
0 [-1,3,-2,-5,4,7,8] -1
1 [3,-2,-5,4,7,8] -2
2 [3,-5,4,7,8] 4
3 [3,4,7,8] 8
你是否看到我们错过了几个值,因为我们正在迭代并修改同样的事情?
现在使用创建副本的切片
(index) (copy) list2 elem
0 [-1,3,-2,-5,4,7,8] [-1,3,-2,-5,4,7,8] -1
1 [-1,3,-2,-5,4,7,8] [3,-2,-5,4,7,8] 3
2 [-1,3,-2,-5,4,7,8] [3,-2,-5,4,7,8] -2
3 [-1,3,-2,-5,4,7,8] [3,-5,4,7,8] -5
4 [-1,3,-2,-5,4,7,8] [3,4,7,8] 4
5 [-1,3,-2,-5,4,7,8] [3,4,7,8] 7
6 [-1,3,-2,-5,4,7,8] [3,4,7,8] 8
我们遍历所有七个值,而不跳过任何值。
仅供参考,list2[:]
相当于list2[0:len(list2):1]
或list(list2)
。
答案 1 :(得分:1)
我会在这里使用列表理解来创建一个包含您要保留的元素的新列表:
numbers = [-1, 3, -2, -5, 4, 7, 8]
positive = [n for n in numbers if n >= 0]
或通过切片分配将新序列重新分配到现有序列中:
numbers = [-1, 3, -2, -5, 4, 7, 8]
numbers[:] = (n for n in numbers if n >= 0)
答案 2 :(得分:1)
在第一个列表中,python正在迭代一个项目,这会导致意外的结果,如您所见。观看:
for elm in list1:
if elm < 0:
list1.remove(elm)
print list1
这将打印:
[3, -2, -5, 4, 7, 8]
[3, -5, 4, 7, 8]
[3, -5, 4, 7, 8]
[3, -5, 4, 7, 8]
[3, -5, 4, 7, 8]
因此,当你删除一个项目后python返回for elm in list1
时,它将不会转到那之后的那个,而是之前的那个(3
)。因此循环。
当你复制list2[:]
时,你实际上并没有迭代list2
而只是一个副本,因此当你删除项目时,你不会删除任何你正在迭代的内容
答案 3 :(得分:0)
切片操作员会复制您正在操作的列表,从而获得准确的结果。