2013-03-15 46 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]