Python中的循环列表迭代器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23416381/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 02:56:36  来源:igfitidea点击:

Circular list iterator in Python

pythonlistiterator

提问by user443854

I need to iterate over a circular list, possibly many times, each time starting with the last visited item.

我需要遍历一个循环列表,可能多次,每次从最后访问的项目开始。

The use case is a connection pool. A client asks for connection, an iterator checks if pointed-to connection is available and returns it, otherwise loops until it finds one that is available.

用例是连接池。客户端请求连接,迭代器检查指向的连接是否可用并返回它,否则循环直到找到可用的连接。

Is there a neat way to do it in Python?

有没有一种巧妙的方法可以在 Python 中做到这一点?

采纳答案by Lukas Graf

Use itertools.cycle, that's its exact purpose:

使用itertools.cycle,这就是它的确切目的:

from itertools import cycle

lst = ['a', 'b', 'c']

pool = cycle(lst)

for item in pool:
    print item,

Output:

输出:

a b c a b c ...

(Loops forever, obviously)

(显然,永远循环)



In order to manually advance the iterator and pull values from it one by one, simply call next(pool):

为了手动推进迭代器并从中提取值,只需调用next(pool)

>>> next(pool)
'a'
>>> next(pool)
'b'

回答by Jacob Krall

The correct answer is to use itertools.cycle. But, let's assume that library function doesn't exist. How would you implement it?

正确答案是使用itertools.cycle。但是,让我们假设库函数不存在。你将如何实施它?

Use a generator:

使用发电机

def circular():
    while True:
        for connection in ['a', 'b', 'c']:
            yield connection

Then, you can either use a forstatement to iterate infinitely, or you can call next()to get the single next value from the generator iterator:

然后,您可以使用for语句进行无限迭代,也可以调用next()以从生成器迭代器中获取单个下一个值:

connections = circular()
next(connections) # 'a'
next(connections) # 'b'
next(connections) # 'c'
next(connections) # 'a'
next(connections) # 'b'
next(connections) # 'c'
next(connections) # 'a'
#....

回答by Ethan Furman

You need a custom iterator -- I'll adapt the iterator from this answer.

您需要一个自定义迭代器——我将从这个答案中调整迭代器。

from itertools import cycle

class ConnectionPool():
    def __init__(self, ...):
        # whatever is appropriate here to initilize
        # your data
        self.pool = cycle([blah, blah, etc])
    def __iter__(self):
        return self
    def __next__(self):
        for connection in self.pool:
            if connection.is_available:  # or however you spell it
                return connection

回答by viky.pat

Or you can do like this:

或者你可以这样做:

conn = ['a', 'b', 'c', 'd', 'e', 'f']
conn_len = len(conn)
index = 0
while True:
    print(conn[index])
    index = (index + 1) % conn_len

prints a b c d e f a b c... forever

打印 abcdefab c... 永远

回答by litepresence

you can accomplish this with append(pop())loop:

你可以用append(pop())循环来完成这个:

l = ['a','b','c','d']
while 1:
    print l[0]
    l.append(l.pop(0))

or for i in range()loop:

for i in range()循环:

l = ['a','b','c','d']
ll = len(l)
while 1:
    for i in range(ll):
       print l[i]

or simply:

或者干脆:

l = ['a','b','c','d']

while 1:
    for i in l:
       print i

all of which print:

所有这些打印:

>>>
a
b
c
d
a
b
c
d
...etc.

of the three I'd be prone to the append(pop()) approach as a function

在这三个中,我倾向于将 append(pop()) 方法作为函数

servers = ['a','b','c','d']

def rotate_servers(servers):
    servers.append(servers.pop(0))
    return servers

while 1:
    servers = rotate_servers(servers)
    print servers[0]

回答by pylang

If you wish to cycle ntimes, implement the ncyclesitertools recipe:

如果您希望循环n时间,请实现ncyclesitertools 配方

from itertools import chain, repeat


def ncycles(iterable, n):
    "Returns the sequence elements n times"
    return chain.from_iterable(repeat(tuple(iterable), n))


list(ncycles(["a", "b", "c"], 3))
# ['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c']