1

好吧,我是 Python 的超级新手,关于切片列表的事情让我很困扰。当我从这段代码中切片 [1] 和 [3] 时,为什么会得到 [1, 3, 4]?

z = [1, 2, 3, 4, 5]
del z[1], z[3]
print z

我以为我会得到 [1, 3, 5] 回来,因为它似乎 [2] 和 [4] 正在被删除。

如果-->[1, 2, 3, 4, 5]
是-->[0, 1, 2, 3, 4]

我的逻辑在哪里搞砸了?

4

5 回答 5

6

第一次删除会更改列表索引,因此下一个不是以前的位置...简化

>>> a = [1, 2, 3]
>>> del a[0] # should delete 1
>>> a
[2, 3]
>>> del a[1] # This use to be the index for 2, but now `3` is at this index
>>> a
[2]
于 2012-12-13T18:16:29.623 回答
3

一次删除一个。第一次删除将所有后续元素向左移动一个位置:

In [3]: z = [1, 2, 3, 4, 5]

In [5]: del z[1]

In [6]: z
Out[6]: [1, 3, 4, 5]

In [7]: z[3]
Out[7]: 5

如果您将索引从最大到最小排列,则不会发生这种情况,因为没有删除会更改任何相关索引:

In [18]: z = [1, 2, 3, 4, 5]

In [19]: del z[3], z[1]

In [20]: z
Out[20]: [1, 3, 5]
于 2012-12-13T18:17:00.970 回答
1

当您进行删除时,它们一次发生一个,因此每次删除都会导致向右的值移动到左侧的一个索引上。

z = [1, 2, 3, 4, 5]

del z[1] # [1, X, 3, 4, 5] --> [1, 3, 4, 5]

del z[3] # [1, 3, 4, X] --> [1, 3, 4]

您应该做的保留顺序是将删除从最大索引到最小索引,这样就不会转移任何内容,

del z[3]; del z[1]

更好的是一次删除所有内容以完全避免该问题:

z = [1, 2, 3, 4, 5]
del z[1::2]
# returns [1, 3, 5]
于 2012-12-13T18:22:43.270 回答
0

其他人提到了您的代码有什么问题,我可以真正理解您打算做什么的原因

如果您想删除第 2 个和第 4 个元素并且不太关心移位列表,您应该在一个单一的范围内执行此操作,可能的解决方案是通过 List COMprehension

def inplace_del(it, rng): 
    return [e for i, e in enumerate(it) if i not in set(rng)]
inplace_del(z,(2,3))
[1, 2, 5]
y = xrange(1,6)
inplace_del(y,(2,3))
[1, 2, 5]

更好的解决方案是使用 itertools

>>> from itertools import count, compress
>>> def in_del(it, rng):
    rng = set(rng)
    holes = (e not in rng for e in count(0))
    return compress(it, holes)

>>> list(in_del(z,(2,3)))
[1, 2, 5]
>>> list(in_del(y,(2,3)))
[1, 2, 5]
>>> 
于 2012-12-13T18:21:36.277 回答
0

您看到这种行为的原因是,这del z[1], z[3]完全等同于在单独的行上设置del z[1]和。del z[3]所以第一个del语句将移动后续元素并z[3]成为最后一个元素(5):

>>> def del_test():
...     del z[1], z[3]
...
>>> def del_test2():
...     del z[1]
...     del z[3]
...
>>> del_test.__code__.co_code == del_test2.__code__.co_code
True
于 2012-12-13T18:22:30.537 回答