繁体   English   中英

Python中的切片列表混乱

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM