简体   繁体   English

如何以每个循环的+1偏移量无限迭代列表

[英]How to iterate through list infinitely with +1 offset each loop

I want to infinitely iterate through the list from 0 to the end, but in the next loop I want to start at 1 to the end plus 0, and the next loop would start at 2 to the end plus 0, 1, up to the last item where it would start again at 0 and go to the end.我想从 0 到结尾无限迭代列表,但是在下一个循环中,我想从 1 开始到结尾加上 0,下一个循环将从 2 开始到结尾加上 0、1,直到最后一个项目,它将从 0 重新开始并走到最后。

Here is my code:这是我的代码:

a = [ 0, 1, 2 ]
offset = 0
rotate = 0

while True:
    print(a[rotate])
    offset += 1
    rotate += 1
    if offset >= len(a):
        offset = 0
        rotate += 1
    if rotate >= len(a):
        rotate = 0

This is the solution I came up with so far.这是我到目前为止提出的解决方案。 It's far from perfect.它远非完美。

The result that I want is:我想要的结果是:

0, 1, 2 # first iteration
1, 2, 0 # second iteration
2, 0, 1 # third iteration
0, 1, 2 # fourth iteration

and so on.等等。

You can use a deque which has a built-in and efficient rotate function (~O(1)):您可以使用具有内置且高效的旋转功能 (~O(1)) 的deque

>>> d = deque([0,1,2])
>>> for _ in range(10):
...     print(*d)
...     d.rotate(-1)  # negative -> rotate to the left
...
0 1 2
1 2 0
2 0 1
0 1 2
1 2 0
2 0 1
0 1 2
1 2 0
2 0 1
0 1 2

Try this:尝试这个:

a = [0, 1, 2]

while True:
    print(*a, sep=', ')
    a.append(a[0])
    a.pop(0)

Output:输出:

0, 1, 2
1, 2, 0
2, 0, 1
0, 1, 2
1, 2, 0
2, 0, 1
...

Or, pop returns the element removed, so it can be simplified或者, pop返回移除的元素,所以可以简化

a = [0, 1, 2]

while True:
    print(*a, sep=', ')
    a.append(a.pop(0))

[Thanks ShadowRanger and Tomerikoo for improvement suggestions.] [感谢 ShadowRanger 和 Tomerikoo 的改进建议。]

You can create the lists with offsets using list slicing, and then repeat them infinitely using itertools.cycle() .您可以使用列表切片创建具有偏移量的列表,然后使用itertools.cycle()无限重复它们。 This computes all of the rotations exactly once, and then cycles through all of them:这仅计算一次所有旋转,然后循环遍历所有旋转:

from itertools import cycle, islice

lst = [0, 1, 2]
items = [lst[i:] + lst[:i] for i in range(len(lst))]
iterator = cycle(items)

for item in islice(iterator, 10):
    print(item)

The above approach is fast once you've gotten past the precomputation, but you may (depending on your use case) prefer an approach that does not have an upfront time/space cost.一旦您通过了预计算,上述方法很快,但您可能(取决于您的用例)更喜欢一种没有前期时间/空间成本的方法。 In that case, you can use a generator instead:在这种情况下,您可以改用生成器:

from itertools import cycle, islice

def rotate(lst):
    for offset in cycle(range(len(lst))):
        yield lst[offset:] + lst[:offset]

lst = [0, 1, 2]
for item in islice(rotate(lst), 10):
    print(item)

Both of these output:这两个输出:

[0, 1, 2]
[1, 2, 0]
[2, 0, 1]
[0, 1, 2]
[1, 2, 0]
[2, 0, 1]
[0, 1, 2]
[1, 2, 0]
[2, 0, 1]
[0, 1, 2]

These code snippets have been improved from a suggestion by wjandrea .这些代码片段已根据wjandrea的建议进行了改进。

Here you have another alternative using pointers:在这里,您还有另一种使用指针的选择:

a = [ 0, 1, 2 ]
i = 0
l = len(a)
while True:
  out = []
  for j in range(i, i+l):
    out.append(a[j%l])
  print(out)
  i=(i+1)%l

Output:输出:

[0, 1, 2]
[1, 2, 0]
[2, 0, 1]
[0, 1, 2]
[1, 2, 0]
[2, 0, 1]

Another option, using list slicing:另一种选择,使用列表切片:

cycles = [a[i:]+a[:i] for i, _ in enumerate(a)]
while True:
    for c in cycles: print(c)

Or, if you don't want to precalculate O(n^2) space for cycles , you can keep making the cycles afresh:或者,如果您不想预先计算cyclesO(n^2)空间,您可以继续重新制作周期:

from itertools import count
n = len(a)
for i in count():
    j = i%n
    print(a[j:]+a[:j])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM