2013-03-15 106 views
4

假設我有一個數組foo,例如,元素[1, 2, 3],並且我想要檢索foo的元素,就像foo已經「無限級聯」一樣。Python中列表的循環索引

例如foo[0:2]將返回(像一個正常的列表):

[1, 2]

foo[0:5]將返回:

[1, 2, 3, 1, 2] 

foo[7:13]將返回:

[2, 3, 1, 2, 3, 1] 

Python或擴展模塊中是否有任何數據容器已經有助於此類訪問?如果沒有,提供這個容器的好方法是什麼?

回答

11

恐怕你得自己去實現它。這是不難,但:

class cyclist(list): 
    def __getitem__(self, index): 
     return list.__getitem__(self, index % len(self)) 

    def __getslice__(self, start, stop): 
     return [self[n] for n in range(start, stop)] 


foo = cyclist([1, 2, 3]) 
print foo[0:2] # [1, 2] 
print foo[7:13] # [2, 3, 1, 2, 3, 1] 
print foo[0:5] # [1, 2, 3, 1, 2] 

它遺漏就像把省略切片中的參數,在片負數,和切片步驟照顧一些細節。

2

當處理看起來像列表但行爲本質不同的序列時,您應該小心。 我會建議使用Pavel Anossov的酷實現,但提供指定的get_cyclic_itemget_cyclic_slice,而不是覆蓋列表的__getitem____getslice__

該類的用戶可以很容易地對他正在使用的列表的行爲(期望ISA關係,如在「循環列表IS列表」中)進行假設,這會導致錯誤/錯誤。

這裏有情況下,使用您的列表可能會比較混亂一些例子,如果主叫方不知道他用cyclicallist而不是常規列表...

a = cyclicallist([ 0, 1, 2 ]) 
# appending a value at the end changes an "existing" index 
print a[100] 
a.append(99) 
print a[100] 
# deleting a value changes an index preceding it 
print a[100] 
del a[999] # currently gives an error: IndexError: list assignment index out of range 
print a[100] # even if no error, what should this print? 
# hmm... 
del a[100:99999] 

和當然,語義的空cyclicallist是不明確......

+2

我不知道OP的上下文,但大多數這些問題似乎可以通過將新數據結構定義爲不可變類型來解決,並且對他/她來說可能足夠了。不是你錯了 - 我也會用你的方法! - 但有趣的是,這樣的約束可以解決一些問題,並且如果OP真的需要這種行爲,那麼約束在OP的問題中也可能是有效的。 – brandizzi 2013-03-15 21:53:55

+2

@brandizzi,好點。也許'class cyclicaltuple(tuple):...'是要走的路。 – shx2 2013-03-15 22:03:24

+0

元組的語義錯誤。元組是具有固定和已知數量的元素的記錄。你也不能稱之爲'騎自行車者':)我認爲這足以發出'騎自行車者'不變的(也許繼承'集合。序列')。 – 2013-03-15 22:35:07

2

即使相比,基於模實施上述建議這將是可笑的低效,我覺得用itertools可能是一個有趣的方式來做到這一點...

>>> from itertools import islice, cycle 
>>> make_cyclic = lambda lst: lambda start, stop: list(islice(cycle(lst), start, stop)) 
>>> make_cyclic([ 1, 2, 3 ]) 
>>> c(7, 13) 
[2, 3, 1, 2, 3, 1]