简体   繁体   English

Python中的切片列表混乱

[英]Slicing List Confusion in Python

Alright, I am super new to Python and something is bugging me about slicing lists. 好吧,我是Python的超级新手,关于切片列表的问题困扰着我。 Why is it that I get [1, 3, 4] back when I am slicing [1] and [3] from this code? 当我从此代码中切片[1]和[3]时,为什么会得到[1、3、4]?

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

I assumed i would be getting [1, 3, 5] back since it appears [2] and [4] are being removed. 我以为我会得到[1、3、5],因为[2]和[4]被删除了。

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

Where is it that my logic is getting messed up? 我的逻辑混乱在哪里?

The first deletion changes the list indices, so the next one isn't where it was before... Simplified 第一次删除会更改列表索引,因此下一个不是以前的位置...简化

>>> 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]

The deletions are done one at a time. 一次删除一次。 The first deletion shifts all the subsequent elements one position to the left: 第一次删除将所有后续元素向左移动一个位置:

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

If you arrange the indices from the largest to the smallest, this doesn't happen since no deletion changes any relevant indices: 如果将索引从最大到最小排列,这不会发生,因为没有删除会更改任何相关索引:

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

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

In [20]: z
Out[20]: [1, 3, 5]

When you are doing your deletions, they happen one at a time, so every deletion causes the rightward values to move over one index to the left. 进行删除时,它们一次会发生一次,因此每次删除都会导致向右的值向左移动一个索引。

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]

What you should do to preserve the order is order your deletions from largest to smallest index so nothing is shifted over, ie, 要保留顺序,您需要做的是将删除操作从最大索引到最小索引进行排序,这样就不会转移任何内容, 即,

del z[3]; del z[1]

Even better is to make all your deletions at once to avoid the problem entirely: 更好的是一次删除所有内容,以完全避免该问题:

z = [1, 2, 3, 4, 5]
del z[1::2]
# returns [1, 3, 5]

Other's have mentioned what is wrong with your code, and I can truly understand the reasoning for what you intend to do 其他人提到了您的代码有什么问题,我可以真正理解您打算做什么的原因

In case you want to delete the 2nd and 4th element and care less about the shifting list, you should do it in a single bredth, a possible solution would be through 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]

A better solution would be to use itertools 更好的解决方案是使用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]
>>> 

The reason you see this behavior is that del z[1], z[3] is exactly equivalent to having del z[1] and del z[3] on separate lines. 您看到此行为的原因是del z[1], z[3]完全等同于在单独的行上包含del z[1]del z[3] So the first del statement will shift subsequent elements and z[3] becomes the last element ( 5 ): 因此,第一个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