簡體   English   中英

Python反向跨步切片

[英]Python reverse-stride slicing

我的問題的一個具體例子是,“在這個例子中我怎樣才能得到‘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],但這會在此過程中創建兩個字符串對象。 我將執行此操作數十億次,因此每個字符串操作都很昂貴。

我一定錯過了一些愚蠢而簡單的東西。 謝謝你的幫助!

只需排除結束范圍索引...

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

具有諷刺意味的是,關於我認為你沒有嘗試過的唯一選擇。

省略切片符號中的結束索引:

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

如果您必須多次這樣做,請創建一個可以反復使用的切片對象

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

如果您正在尋找比擴展切片符號更易讀的東西:

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

閱讀“技術文檔”( 此處)后 - 特別是這句話:

如果任一邊界為負,則將序列的長度添加到其中。

我決定試試這個,它奏效了:

>>> 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' 的值

您可以使用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]:
    ...

您將無法處理i0的情況,因為您實際上是在將foo[0:3]foo[2:-1:-1] ,這相當於foo[2:n-1:-1] ,這又是一個空字符串。

第一個解決方案的唯一缺點是它使用了更多的內存,但這沒什么大不了的。

除了上述解決方案,您還可以執行以下操作:

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

我想如果 foo 會改變長度,這可能不是最好的解決方案,但如果長度是靜態的,它會起作用。

鑒於:

>>> foo = '0123456'

所需的字符串3210是從索引 3rd 到第 0 個字符:

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

這里有兩個通用的解決方案:

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

     >>> foo[stop_idx:start_idx+1][::-1] '3210'
  2. 基於此答案,在第一個元素之前使用負步並停止 1 個元素(加上停止偏移量):

     >>> foo[start_idx:stop_idx-len(foo)-1:-1] '3210' >>> a[start_idx:stop_idx-len(a)-1:-1] [2, 1]

比較執行時間,第一個版本更快:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM