[英]Slicing List Confusion in Python
好吧,我是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]
我的逻辑混乱在哪里?
第一次删除会更改列表索引,因此下一个不是以前的位置...简化
>>> 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]
一次删除一次。 第一次删除将所有后续元素向左移动一个位置:
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]
进行删除时,它们一次会发生一次,因此每次删除都会导致向右的值向左移动一个索引。
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]
其他人提到了您的代码有什么问题,我可以真正理解您打算做什么的原因
如果您想删除第二和第四元素,而不在乎移位列表,则应在单个列表中进行操作,可能的解决方案是通过列表合并
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]
>>>
您看到此行为的原因是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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.