[英]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]:
...
您將無法處理i
為0
的情況,因為您實際上是在將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
這里有兩個通用的解決方案:
取前向切片然后反轉它:
>>> foo[stop_idx:start_idx+1][::-1] '3210'
基於此答案,在第一個元素之前使用負步並停止 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.