假設我有如下清單:
lst = [0,10,20,30,40,50,60,70]
我希望元素從 lst fromindex = 5到index = 2回圈順序。
lst[5:2][]
我想要的產量lst[5:2] = [50,60,70,0,10]。有沒有簡單的庫函式來做到這一點?
uj5u.com熱心網友回復:
如果第二項小于第一項,只需將切片一分為二:
lst = [0,10,20,30,40,50,60,70]
def circslice(l, a, b):
if b>=a:
return l[a:b]
else:
return l[a:] l[:b]
circslice(lst, 5, 2)
輸出: [50, 60, 70, 0, 10]
uj5u.com熱心網友回復:
deque按照評論中的建議使用 a :
from collections import deque
d = deque(lst)
a,b = 5,2
d.rotate(-a)
list(d)[:len(lst)-a b]
注意。我發現它不是很實用,因為它需要復制串列來創建雙端佇列,并復制另一個副本來切片
uj5u.com熱心網友回復:
對于允許您仍然使用本機切片語法并保持靜態型別兼容性的東西,您可以在您的序列周圍使用輕量級包裝類:
from typing import Generic, Protocol, TypeVar
S = TypeVar('S', bound="ConcatSequence")
class CircularView(Generic[S]):
def __init__(self, seq: S) -> None:
self.seq = seq
def __getitem__(self, s: slice) -> S:
if s.start <= s.stop:
return self.seq[s]
else:
wrap = len(self.seq) % s.step if s.step else 0
return self.seq[s.start::s.step] self.seq[wrap:s.stop:s.step]
lst = [0, 10, 20, 30, 40, 50, 60, 70]
print(CircularView(lst)[2:5]) # [20, 30, 40]
print(CircularView(lst)[5:2]) # [50, 60, 70, 0, 10]
print(CircularView(lst)[5:2:2]) # [50, 70, 0]
print(CircularView(lst)[5:3:2]) # [50, 70, 0, 20]
print(CircularView(lst)[4:3:3]) # [40, 70, 20]
帶有靜態型別的可選協議
class ConcatSequence(Protocol):
"""
A sequence that implements concatenation via '__add__'.
This protocol is required instead of using
'collections.abc.Sequence' since not all sequence types
implement '__add__' (for example, 'range').
"""
def __add__(self, other):
...
def __getitem__(self, item):
...
def __len__(self):
...
此方法通過 mypy 進行型別檢查。
uj5u.com熱心網友回復:
你可以使用這樣的函式:
def circular_indexing(list_, start_index, end_index) -> list:
return [*list_[start_index:len(list_)], *list_[0:end_index]]
例如:
list1 = [0, 1, 2, 3]
def circular_indexing(list_, start_index, end_index) -> list:
return [*list_[start_index:len(list_)], *list_[0:end_index]]
print(circular_indexing(list1, 2, 1))
輸出:[2, 3, 0]
uj5u.com熱心網友回復:
這個問題有兩種快速/簡單的解決方案。
第一個也是更復雜的方法是覆寫 pythonlist.__getitem__方法的默認 python 庫實作,它已在 StackOverflow 的其他地方被參考。
這將允許您像往常一樣參考切片,即list[5:3],并且理論上它會按照您定義的方式運行。這將是默認庫的“本地擴展”。
相反,您可以實作自己的函式,該函式將以回圈方式迭代您的串列,滿足您自己的標準。一些偽代碼:
def foo(left_idx, right_idx):
if right_idx < left_idx:
wrap index when right bound has been reached
else:
iterate normally
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/382231.html
