为什么带有负步长的 Python 切片会给出看似相等的索引的不同输出?

Why does Python's slice with a negative step give different outputs with seemingly equal indexes?

提问人:hcmcnae 提问时间:5/31/2023 最后编辑:hcmcnae 更新时间:5/31/2023 访问量:63

问:

我正在解决一个 leetcode 问题,以找到字符串中最长的回文。使用 Python 的切片,我想检查窗口大小的切片向前和向后是否相同。我发现切片有一些奇怪的行为,我想知道是否有人可以解释。

当我向前和向后检查字符串的切片时,我在切片上遇到了一些奇怪的行为。

这是我正在尝试的代码。

wl = 0
ans = ""
        
while 1:
  if wl == len(s)-1: return ans
            
  wr = wl + 1
  while wr < len(s):
    if s[wl] == s[wr] and s[wl:wr+1] == s[wr:wl:-1]: # Weird behavior occurs here
      if len(s[wl:wr+1]) > len(ans):
        ans = s[wl:wr+1]
    wr += 1
            
  wl += 1

我在单独的 python 脚本中运行了一些测试,以查看切片发生了什么:

string = "abcde"

s[0:3]     # Outputs "abc"
s[2:0:-1]  # Outputs "cb" rather than "cba"

所以我看到的是在 string[start:stop:step] 中,start 是包含的,stop 是排他性的。

然后,向后索引字符串,即:

string = "abcde"
s[0:3]     # Outputs "abc"
s[2:-6:-1] # Outputs "cba", which is what I want.

现在这就是我感到困惑的地方。

s[2:-6:-1] 将字符串从 s[2]='c' 切成 s[-6]='a',步长 -1。

S[2:0:-1] 理论上也应该这样做吗?

s[2:-6:-1] => "cba" 
s[2:0:-1]  => "cb"     

为什么 s[2:-6:-1] 给了我我想要的结果,而 s[2:0:-1] 给了我不同的东西?

Python 字符串 切片

评论

0赞 SimonUnderwood 5/31/2023
负指数从 -1 开始。这意味着是,是......而不是.e-1d-2a-5-6
0赞 hcmcnae 5/31/2023
哦,我什至没有尝试 s[-6] 来查看它不在索引范围内。感谢您的回复,我明白我的误解在哪里!@SimonUnderwood

答:

-1赞 Abrar Ahmed 5/31/2023 #1

所以这里的问题是结束索引是排他性的。所以如果我们这样做了

s[0:3] # outputs [s[0],s[1],s[2]]

我们得到“ABC”,并排除了结束索引(即 3)。

如果我们这样做

s[2:0:-1] # outputs [s[2], s[1]]

我们得到“CB”,结束索引(即 0)仍然被排除在外

现在,由于 Python 中的负指数看起来像这样

   a     b     c     d     e
 s[0]  s[1]  s[2]  s[3]  s[4]
s[-5] s[-4] s[-3] s[-2] s[-1]

由于负指数可以与 Python 中的正指数互换使用,我们可以这样做

s[2:-6:-1]
# and we end up looking at
   c     b     a 
 s[2]  s[1]  s[0]
s[-3] s[-4] s[-5]
# index -6 is still excluded
# note: -6 is out of bounds and wouldn't add to the result if included

您应该执行 s[2:-6:-1] 以在代码中获得所需的结果
,这将是

s[wl:wr+1] == s[wr:wl-len(s)-1:-1]

评论

0赞 hcmcnae 5/31/2023
使用 s[2:-1:-1] 根本没有输出,这是我困惑的一部分。相反,我发现我必须使用“-len(s)-1 + wl”作为我的止损,这给了我正确的负指数。
0赞 Abrar Ahmed 5/31/2023
我的坏......编辑了答案以解决此问题。
0赞 Alain T. 5/31/2023 #2

下标的第二部分是停止值(因此被排除在外):

因此:

s[wl:wr+1]   # will include indexes wl...wr
s[wr:wl:-1]  # will include indexes wr...(wl+1)

由于进度是倒退的,它将按倒序在 wl 前面的索引处停止:[wr,...,wl+3,wl+2,wl+1]

wl = 3 
wr = 6
s = [0, 1, 2, 3, 4, 5, 6, 7, 8] # using indexes to illustrate

s[wr:wl:-1] # [6, 5, 4] (3 is the stop value so it is not included) 

s[wr:wl-1:-1]  # [6, 5, 4, 3]

这样想吧,你必须使用向前步进 1,所以你需要使用 -1 的后退是有道理的wr+1wl-1

话虽如此,当您使用正索引时,您需要小心使用负步骤,因为当您想要包含第一个字符时,它们可能会让您感到惊讶。当 wl 为零时,将返回一个空字符串,而不是开始。这是因为 -1 表示最后一个字符,而不是索引 0 之前的虚部位置。负指数可能事先在内部转换为正指数。
要解决此问题,您可以将其编写为 或
s[wr:wl-1:-1]s[wl:wr][::-1]s[wr:wl-1-len(s):-1]

评论

0赞 hcmcnae 5/31/2023
感谢您的回复和解释!我喜欢你对 s[wl:wr][::-1] 的建议。