4

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 中是否有任何数据容器或扩展模块已经促进了这种类型的访问?如果不是,那么提供这个容器的好/简单的方法是什么?

4

3 回答 3

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]

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

于 2013-03-15T20:39:23.123 回答
2

在处理看起来像列表但行为本质上不同的序列时,您应该小心。我建议使用 Pavel Anossov 的酷实现,但提供指定的get_cyclic_itemand get_cyclic_slice,而不是覆盖列表的__getitem__and __getslice__

该类的用户可以轻松地对他正在使用的列表的行为做出假设(期望 ISA 关系,如“cyclicallist IS A list”),这将导致错误/错误。

cyclicallist如果调用者不知道他使用的是 a而不是常规列表,以下是使用列表可能会令人困惑的情况的一些示例...

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没有明确定义......

于 2013-03-15T20:56:16.397 回答
2

即使与上面建议的基于模的实现相比效率低得离谱,我认为使用它itertools可能是一种有趣的方式......</p>

>>> 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]
于 2013-03-16T01:09:06.723 回答