16

在我解释我的问题时请耐心等待。如果您已经了解扩展切片列表索引,请跳至粗体标题。

在 python 中,您可以使用切片表示法对列表进行索引。这是一个例子:

>>> A = list(range(10))
>>> A[0:5]
[0, 1, 2, 3, 4]

您还可以包含一个步幅,其作用类似于“步”:

>>> A[0:5:2]
[0, 2, 4]

步幅也允许为负数,这意味着以相反的顺序检索元素:

>>> A[5:0:-1]
[5, 4, 3, 2, 1]

可是等等!我想看看[4, 3, 2, 1, 0]。哦,我明白了,我需要减少开始和结束索引:

>>> A[4:-1:-1]
[]

发生了什么?它将 -1 解释为位于数组的末尾,而不是开头。我知道您可以按如下方式实现:

>>> A[4::-1]
[4, 3, 2, 1, 0]

但是你不能在所有情况下都使用它。例如,在已传递索引的方法中。

我的问题是:

是否有任何好的 Pythonic 方式来使用具有负步幅的扩展切片以及包含序列第一个元素的显式开始和结束索引?

这是我迄今为止提出的,但似乎并不令人满意。

>>> A[0:5][::-1]
[4, 3, 2, 1, 0]
4

9 回答 9

5

start更改和的语义很容易出错stop。使用Noneor-(len(a) + 1)代替0or -1。语义不是任意的。请参阅 Edsger W. Dijkstra 的文章“为什么编号应该从零开始”

>>> a = range(10)
>>> start, stop, step = 4, None, -1

或者

>>> start, stop, step = 4, -(len(a) + 1), -1
>>> a[start:stop:step]
[4, 3, 2, 1, 0]

或者

>>> s = slice(start, stop, step)
>>> a[s]
[4, 3, 2, 1, 0]

什么时候s是一个序列,其中的负索引s[i:j:k]被特殊处理

如果iorj为负数,则索引相对于字符串的结尾: len(s) + iorlen(s) + j被替换。但请注意,-0仍然是0.

这就是为什么,len(range(10)[4:-1:-1]) == 0因为它相当于range(10)[4:9:-1].

于 2008-12-30T12:06:23.797 回答
2

好的,我想这可能和我能得到的一样好。感谢 Abgan 激发了这个想法。这依赖于切片中的 None 被视为缺少参数的事实。有人有更好的吗?

def getReversedList(aList, end, start, step):
    return aList[end:start if start!=-1 else None:step]

编辑:检查start==-1,不是0

这仍然不理想,因为您破坏了 -1 的通常行为。似乎这里的问题是应该发生的事情的两个重叠定义。无论谁获胜,都会取消寻找其他意图的其他有效调用。

于 2008-12-29T23:44:35.417 回答
2
[ A[b] for b in range(end,start,stride) ]

较慢,但是您可以使用负索引,因此应该可以:

[ A[b] for b in range(9, -1, -1) ]

我意识到这不是使用切片,但我认为如果专门使用切片来获取结果不是优先事项,我还是会提供解决方案。

于 2008-12-30T00:10:05.550 回答
1

我相信以下内容不能满足您:

def getReversedList(aList, end, start, step):
    if step < 0 and start == 0:
         return aList[end::step]
    return aList[end:start:step]

或者是吗?:-)

于 2008-12-29T23:38:30.310 回答
1

但是,例如,如果您将索引存储在变量中,则不能使用它。

这令人满意吗?

>>> a = range(10)
>>> start = 0
>>> end = 4
>>> a[4:start-1 if start > 0 else None:-1]
[4, 3, 2, 1, 0]
于 2008-12-30T11:41:43.067 回答
1

正如你所说,很少有人完全理解扩展切片所能做的一切,所以除非你真的需要额外的性能,否则我会以“明显”的方式来做:

rev_subset = reversed(data[start:stop])

于 2008-12-30T15:01:08.077 回答
0
a[4::-1]

例子:

Python 2.6 (r26:66714, Dec  4 2008, 11:34:15) 
[GCC 4.0.1 (Apple Inc. build 5488)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[4:0:-1]
[4, 3, 2, 1]
>>> a[4::-1]
[4, 3, 2, 1, 0]
>>> 

原因是第二项被解释为“while not index ==”。忽略它是“在范围内的索引”。

于 2008-12-29T23:33:18.417 回答
0

我知道这是一个老问题,但如果像我这样的人正在寻找答案:

>>> A[5-1::-1]
[4, 3, 2, 1, 0]

>>> A[4:1:-1]
[4, 3, 2]
于 2011-01-04T23:17:45.280 回答
0

你可以使用一个slice(start, stop, step)对象,它是这样的

s=slice(start, stop, step)
print a[s]

是相同的

print a[start : stop : step]

此外,您可以将任何参数设置为None在冒号之间不表示任何内容。因此,在您提供的情况下,您可以使用slice(4, None, -1).

于 2011-01-04T23:52:24.850 回答