Итератор кругового списка в Python



Мне нужно перебирать круговой список, возможно, много раз, каждый раз, начиная с последнего посещенного элемента.



прецедент-это пул соединений. Клиент запрашивает соединение, итератор проверяет, доступно ли указанное соединение, и возвращает его, в противном случае циклы до тех пор, пока он не найдет то, что доступно.



есть аккуратный способ сделать это в Python?

734   6  

6 ответов:

использовать itertools.cycle, это его точное назначение:

from itertools import cycle

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

pool = cycle(lst)

for item in pool:
    print item,

выход:

a b c a b c ...

(петли навсегда, очевидно)


чтобы вручную продвигать итератор и извлекать из него значения по одному, просто вызовите next(pool):

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

правильный ответ-использовать itertools.цикл. Но, предположим, что библиотечная функция не существует. Как бы вы это реализовали?

использовать генератор:

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

затем вы можете использовать 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'
#....

или вы можете сделать так:

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

печать Б В Г Д Е А Б... навсегда

вы можете сделать это с append(pop()) петли:

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

или for i in range() петли:

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

или просто:

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

while 1:
    for i in l:
       print i

все печатать:

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

из трех я был бы склонен к 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]

вам нужен пользовательский итератор -- я адаптирую итератор из ответ.

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

Если вы хотите, чтобы цикл n раз, использовать тег ncyclesрецепт модуле itertools:

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']

Comments

    Ничего не найдено.