繁体   English   中英

使用切片表示法反转列表

[英]Reversing a list using slice notation

在以下示例中:

foo = ['red', 'white', 'blue', 1, 2, 3]

其中: foo[0:6:1]将打印 foo 中的所有元素。 但是, foo[6:0:-1]将省略第 1 个或第 0 个元素。

>>> foo[6:0:-1]
[3, 2, 1, 'blue', 'white']

我知道我可以使用 foo.reverse() 或 foo[::-1] 反向打印列表,但我试图理解为什么 foo[6:0:-1] 不打印整个列表?

简而言之,切片符号:

[ <first element to include> : <first element to exclude> : <step> ]

如果要在反转列表时包含第一个元素,请将中间元素留空,如下所示:

foo[::-1]

您还可以在这里找到一些关于 Python 切片的一般信息:
解释 Python 的切片符号

如果您在记住切片符号时遇到困难,可以尝试使用Hokey Cokey

[输入输出摇一摇]

[要包含的第一个元素:要省略第一个元素:使用的步骤]

YMMV

...为什么 foo[6:0:-1] 不打印整个列表?

因为中间值是排他的,而不是包容的,停止值。 区间表示法是 [start, stop)。

这正是 [x]range 的工作原理:

>>> range(6, 0, -1)
[6, 5, 4, 3, 2, 1]

这些是包含在结果列表中的索引,它们不包括第一项的 0。

>>> range(6, -1, -1)
[6, 5, 4, 3, 2, 1, 0]

另一种看待它的方式是:

>>> L = ['red', 'white', 'blue', 1, 2, 3]
>>> L[0:6:1]
['red', 'white', 'blue', 1, 2, 3]
>>> len(L)
6
>>> L[5]
3
>>> L[6]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

索引 6 超出(精确地过去) L 的有效索引,因此将其从范围中排除为排除的停止值:

>>> range(0, 6, 1)
[0, 1, 2, 3, 4, 5]

仍然为您提供列表中每个项目的索引。

这个答案可能有点过时,但它可能对遇到同样问题的人有所帮助。 您可以获得具有任意结尾的反向列表 - 最多为 0 索引,应用第二个就地切片,如下所示:

>>> L = list(range(10))
>>> L
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> (start_ex, end) = (7, 0)
>>> L[end:start_ex][::-1]
[6, 5, 4, 3, 2, 1, 0]

利用

>>>foo[::-1]

这将显示列表从结束元素到开始的反向,

如果您使用负停止值,您可以让它工作。 尝试这个:

foo[-1:-7:-1]

补充。 以 2 步反转:

A = [1,2,2,3,3]
n = len(A)
res = [None] * n
mid = n//2 + 1 if n%2 == 1 else n//2

res[0::2] = A[0:mid][::-1]
res[1::2] = A[0:mid][::-1]
print(res)

[2、3、2、3、1]

andrew-clark的答案形式化一点:

假设列表vv[n1:n2:n3]切片。 n1是初始 position, n2是最终 position, n3是步骤

让我们以 Python 的方式编写一些伪代码:

n3 = 1  if (n3 is missing) else n3
if n3==0:
   raise exception # error, undefined step

第一部分:n3正

if n3>0:
   slice direction is from left to right, the most common direction         

   n1 is left slice position in `v` 
   if n1 is missing: 
      n1 = 0   # initial position
   if n1>=0:
      n1 is a normal position
   else: 
     (-n1-1) is the position in the list from right to left 

   n2 is right slice position in `v` 
   if n2 is missing: 
      n2 = len(x)  # after final position
   if n2>=0:
      n2 is a normal final position (exclusive)
   else: 
      -n2-1 é the final position in the list from right to left 
       (exclusive)

第二部分:n3负

else: 
  slice direction is from right to left (inverse direction)

  n1 is right slice position in `v` 
  if n1 is missing: 
     n1 = -1   # final position is last position in the list.
  if n1>=0:
     n1 is a normal position
  else: 
     (-n1-1) is the position in the list from right to left 

  n2 is  left slice position in `v` 
  if n2 is missing: 
     n2 = -len(x)-1   # before 1st character  (exclusive)
  if n2>=0:
     n2 is a normal final position (exclusive)
  else: 
     -n2-1 is the ending position in the list from right to left 
     (exclusive)

现在原来的问题:如何用切片符号反转列表?

L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(L(::-1)) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

为什么?
n1 is missing and n3<0 => n1=0
n2 is missing and n3<0 => n2 = -len(x)-1

所以L(::-1) == L(-1:-11:-1)

这是一个非常好的问题,在我看来,以上答案都没有真正回答所提出的问题。 部分原因是理智诚实的答案可能会揭示 Python 类型系统的弱点。 其他一些语言也存在同样的弱点。

更理智的回答可能是: Python 切片不能很好地概括。

准确地说,可以使用collection[begin:end]沿一个方向遍历集合,但collection[end:begin:-1]不起作用。 它不起作用,因为第一个索引是0但“第一个索引之前的索引”不是-1 因此, collection[end:-1:-1]的评估结果并不符合我们的合理预期。

[first to include: first to exclude: step]的解释是有缺陷的。 如果“第一个排除”是第一个元素之前的那个,则不能以与想要包含相同的第一个元素的情况相同的方式表达它。

总之,你并不疯狂地期待普遍性,它只是不存在。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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