首页 文章

扩展切片,以负步幅进入序列的开头

提问于
浏览
13

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

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

9 回答

  • 1

    更改 startstop 的语义很容易出错 . 使用 None-(len(a) + 1) 而不是 0-1 . 语义不是任意的 . 参见Edsger W. Dijkstra的文章"Why numbering should start at zero" .

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

    When s is a sequence the negative indexes in s[i:j:k] are treated specially

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

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

  • 1

    好吧,我认为这可能和我能得到的一样好 . 感谢Abgan激发了这个想法 . 这取决于切片中的None被视为缺少参数的事实 . 谁有更好的东西?

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

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

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

  • 0
    [ A[b] for b in range(end,start,stride) ]
    

    较慢,但你可以使用负指数,所以这应该工作:

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

    我意识到这不是使用切片,但是如果使用切片专门用于获得结果不是优先级,我认为无论如何我都会提供解决方案 .

  • 0

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

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

    还是吗? :-)

  • 5

    但是,如果您将索引存储在变量中,则无法使用它 .

    这令人满意吗?

    >>> a = range(10)
    >>> start = 0
    >>> end = 4
    >>> a[4:start-1 if start > 0 else None:-1]
    [4, 3, 2, 1, 0]
    
  • 2

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

    rev_subset = reversed(data[start:stop])

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

    原因是第二项被解释为“而不是索引==” . 离开它是“在范围内的指数” .

  • 1

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

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

    您可以使用 slice(start, stop, step) 对象,就是这样

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

    是相同的

    print a[start : stop : step]
    

    而且,您可以将 None 的任何参数设置为在冒号之间没有任何内容 . 因此,在您给出的情况下,您可以使用 slice(4, None, -1) .

相关问题