Python中列表的循环索引

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

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]

缺少一些细节,比如处理省略的切片参数、切片中的负数以及切片步长。


2
当处理看起来像列表但本质上行为不同的序列时,你应该要小心。我建议使用Pavel Anossov的实现,但提供指定的get_cyclic_itemget_cyclic_slice,而不是覆盖列表的__getitem____getslice__
类的用户很容易对他正在使用的列表的行为做出假设(期望一个ISA关系,就像“循环列表IS A列表”一样),这将导致错误/bug。
以下是一些例子,说明在不知道自己使用的是而不是常规列表的情况下,使用您的列表可能会变得混乱...
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]

当然,空的的语义是没有明确定义的...

2
我不知道OP的上下文,但是大多数这些问题似乎可以通过将新数据结构定义为不可变类型来解决,并且对于他/她来说可能已经足够了。并不是说你错了 - 我也会使用你的方法! - 但有趣的是,这样的限制可以解决一些问题,如果OP确实需要这种行为,那么这个限制在OP的问题中也可能是有效的。 - brandizzi
2
@brandizzi,说得好。也许 class cyclicaltuple(tuple): ... 是一个不错的选择。 - shx2
一个元组在语义上是错误的。元组是具有固定和已知数量的元素的记录。而且你不能称之为 cyclist :) 我认为宣布 cyclist 不可变就足够了(也许可以从 collections.Sequence 继承)。 - Pavel Anossov
我明白你不能称之为“cyclist”的原因,这是一个明显的障碍。但我不确定你所说的语义是什么意思。我认为元组只是不可变列表。 - shx2
这基本上概括了我的观点:http://jtauber.com/blog/2006/04/15/python_tuples_are_not_just_constant_lists/。 - Pavel Anossov

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]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接