Python反向跨越切片

时间:2011-04-27 00:50:57

标签: python string slice

我的问题的一个具体例子是,“我在这个例子中如何获得'3210'?”


>>> foo = '0123456'
>>> foo[0:4]
'0123'
>>> foo[::-1]
'6543210'
>>> foo[4:0:-1] # I was shooting for '3210' but made a fencepost error, that's fine, but...
'4321'
>>> foo[3:-1:-1] # How can I get '3210'?
''
>>> foo[3:0:-1]
'321'

似乎很奇怪我可以写foo [4:0:-1],foo [5:1:-1]等,并得到我所期望的,但是没有办法写切片让我得到'3210'。

执行此操作的临时方法是foo [0:4] [:: - 1],但这会在进程中创建两个字符串对象。我将在数十亿次执行此操作,因此每个字符串操作都很昂贵。

我必须遗漏一些愚蠢而容易的东西。谢谢你的帮助!

8 个答案:

答案 0 :(得分:37)

只需排除结束范围索引......

>>> foo[3::-1]
'3210'
讽刺的是,关于我认为你没有尝试的唯一选择。

答案 1 :(得分:8)

如果你正在寻找比扩展切片符号更人性化的东西:

>>> foo = '0123456'
>>> ''.join(reversed(foo[0:4]))
'3210'

答案 2 :(得分:6)

在切片表示法中省略结束索引:

>>> foo = '0123456'
>>> foo[3::-1]
'3210'

如果必须多次这样做,请创建一个可以反复使用的切片对象

>>> i = slice(3,None,-1)
>>> foo[i]
'3210'

答案 3 :(得分:3)

您可以使用s[::-1]来反转整个字符串。但是,如果要以固定长度反转每个子字符串,可以先提取子字符串,然后反转整个子字符串。例如,假设我们需要检查字符串foo的长度为3的每个子字符串是否为回文,我们可以这样做:

>>> foo = '0102030'
>>> for i in range(len(foo)-3):
...     if foo[i:i+3] == foo[i:i+3][::-1]:
...         print(foo[i:i+3], 'is a palindrome')
...     else:
...         print(foo[i:i+3], 'is not a palindrome')
...
010 is a palindrome
102 is not a palindrome
020 is a palindrome
203 is not a palindrome
030 is a palindrome

如果你想检查子串是否是这样的回文:

if foo[i:i+3] == foo[i+2:i-1:-1]:
    ...

您将无法处理i 0的情况,因为您实际上是将foo[0:3]foo[2:-1:-1]进行比较,这相当于foo[2:n-1:-1] },而这又是一个空字符串。

第一个解决方案的唯一缺点是它使用了更多的内存,但这没什么大不了的。

答案 4 :(得分:3)

阅读“技术文档”(here)后 - 特别是句子:

  

如果任一边界为负数,则将序列的长度添加到其中。

我决定尝试这个,它有效:

>>> foo = '0123456'
>>> foo[3:-1-len(foo):-1]
'3210'
>>>

所以我认为以编程方式确定“终点”的最佳答案是提供一个命名良好的辅助函数,该函数清楚地表明其参数总是被视为正偏移,可能是special_slice()

我认为这种“特殊”情况的清晰度非常重要,因为许多常见和重要的用例取决于负偏移的默认行为(即向它们添加长度)。就个人而言,我经常使用'-1'终点来表示:在最后一个元素之前停止。

所以,根据你的评论:

  

...算法的工作方式如下:foo [i:i-4:-1],以高'i'开头并向下走。

我可能会做以下事情:

def slice_by_len(data, start, length, step=1):
    end = start + length if step > 0 else start - length
    if end < 0:
        # Fix the negative offset to get what we really want
        end -= len(data)
    return data[start:end:step]

然后为每个切片调用它:

foo_part = slice_by_len(foo, i, 4, -1)

以上内容很容易绕过'i'

的值

答案 5 :(得分:1)

除上述解决方案外,您还可以执行以下操作:

foo = '0123456'
foo[-4::-1]

我想如果foo将会改变长度,这可能不是最好的解决方案,但如果长度是静态的,那就可以了。

答案 6 :(得分:0)

假设:

>>> foo = '0123456'

所需的字符串3210是从索引3到第0个字符:

>>> stop_idx=0
>>> start_idx=3

以下是两种通用解决方案:

  1. 取向前切片然后反转它:

    >>> foo[stop_idx:start_idx+1][::-1]
    '3210'
    
  2. 基于this answer,使用否定步骤并在第一个元素之前停止1个元素(加上停止偏移量):

    >>> foo[start_idx:stop_idx-len(foo)-1:-1]
    '3210'
    
    >>> a[start_idx:stop_idx-len(a)-1:-1]
    [2, 1]
    
  3. 比较执行时间,第一个版本更快:

    >>> timeit.timeit('foo[stop_idx:start_idx+1][::-1]', setup='foo="012345"; stop_idx=0; start_idx=3', number=10_000_000)
    1.7157553750148509
    >>> timeit.timeit('foo[start_idx:stop_idx-len(foo)-1:-1]', setup='foo="012345"; stop_idx=0; start_idx=3', number=10_000_000)
    1.9317215870250948
    

答案 7 :(得分:-2)

s="this is my world"
pattern=re.findall(r'\S+',s)
a=[]
for i in range(len(pattern)):
    a.append((pattern[i][::-1]))
print (a)
print (" ".join(a))