Python中列表的循环索引

时间:2013-03-15 20:26:15

标签: python data-structures

假设我有一个数组foo,例如元素[1, 2, 3],我希望检索foo的元素,就好像foo已经“无限连接”。

例如foo[0:2]会返回(就像普通列表一样):

[1, 2]

foo[0:5]会返回:

[1, 2, 3, 1, 2]

foo[7:13]会返回:

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

Python或扩展模块中是否有任何数据容器已经促进了此类访问?如果没有,那么提供这个容器的好方法是什么?

3 个答案:

答案 0 :(得分: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]

缺少一些细节,例如处理省略的切片参数,切片中的负数和切片步骤。

答案 1 :(得分:2)

使用看起来像列表但行为本身不同的序列时应该小心。 我建议使用Pavel Anossov的酷实现,但提供指定的get_cyclic_itemget_cyclic_slice,而不是覆盖列表的__getitem____getslice__

该类的用户可以轻松地假设他正在使用的列表的行为(期望ISA关系,如“循环列表是一个列表”),这将导致错误/错误。

以下是一些例子,如果调用者不知道他使用的是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 :(得分: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]