代码之家  ›  专栏  ›  技术社区  ›  recursive

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

  •  13
  • recursive  · 技术社区  · 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]
    

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

    我的问题是:

    有没有好的使用负跨步的扩展切片的方法 以及明确的开始和结束索引 包括序列的第一个元素?

    这是我到目前为止想出来的,但似乎不令人满意。

    >>> A[0:5][::-1]
    [4, 3, 2, 1, 0]
    
    9 回复  |  直到 11 年前
        1
  •  5
  •   jfs    11 年前

    这是一个容易改变语义的错误 start stop . 使用 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 仍然是 .

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

        2
  •  2
  •   recursive    16 年前

    好吧,我想这可能和我要买的一样好。多亏了艾布根激发了这个想法。这依赖于这样一个事实:切片中的任何一个都不会被视为缺少参数。有人有更好的吗?

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

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

    这仍然是不理想的,因为你正在击倒-1的常规行为。这里的问题似乎是对应该发生的事情有两个重叠的定义。无论谁赢了,都会拿走寻找另一个目的的有效呼叫。

        3
  •  2
  •   codelogic    16 年前
    [ A[b] for b in range(end,start,stride) ]
    

    但速度较慢,您可以使用负指数,因此这应该有效:

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

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

        4
  •  1
  •   Abgan    16 年前

    我认为以下内容不符合您的要求:

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

    还是这样?-)

        5
  •  1
  •   Community CDub    8 年前

    But 如果你是,你就不能用它 将索引存储在变量中 例子。

    这令人满意吗?

    >>> a = range(10)
    >>> start = 0
    >>> end = 4
    >>> a[4:start-1 if start > 0 else None:-1]
    [4, 3, 2, 1, 0]
    
        6
  •  1
  •   James Antill    16 年前

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

    rev_subset = reversed(data[start:stop])

        7
  •  0
  •   Charlie Martin    16 年前
    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==”。去掉它就是“索引在范围内”。

        8
  •  0
  •   xiao-yu    14 年前

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

    >>> A[5-1::-1]
    [4, 3, 2, 1, 0]
    
    >>> A[4:1:-1]
    [4, 3, 2]
    
        9
  •  0
  •   Andrew Jaffe    14 年前

    你可以使用 slice(start, stop, step) 对象,即

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

    是一样的

    print a[start : stop : step]
    

    而且,您可以将任何参数设置为 None 在两个冒号之间没有任何指示。所以在你给的情况下,你可以用 slice(4, None, -1) .