2

In the following two examples, I am trying to remove negative element from a list using two different types of looping.

First I tried by using normal looping for i in list but in this case when i do list1.remove(elm) the size of the list is reduce by one element. So, in the next loop the second element moves to the first element position. So, the second element is missed from testing if elm < 0 in the next loop. So, it doesn't remove all the negative element from the list.

Secondly, I tried using slicing. What i understood from slicing is it creates a temporary list. So, when i do for i in list2[:] it creates a new temporary list2 = [-1,3,-2,-5,4,7,8] but still I didn't get a clear picture, how it works. It removes all the negative element.

#!/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]
4

4 回答 4

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]or list(list2)

于 2013-11-03T03:14:18.230 回答
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)
于 2013-11-03T03:14:54.903 回答
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]

for elm in list1因此,当您在删除一项后python返回时,它不会转到之后的那个,而是之前的那个( 3)。因此循环。

当你制作一个副本时list2[:],你实际上并没有迭代,list2而只是一个副本,因此当你删除项目时,你并没有删除任何你正在迭代的东西。

于 2013-11-03T03:15:32.157 回答
0

切片运算符复制您正在操作的列表,从而获得准确的结果。

于 2013-11-03T03:29:59.950 回答