Python의 순환 목록 반복기


99

마지막으로 방문한 항목부터 시작할 때마다 순환 목록을 여러 번 반복해야합니다.

유스 케이스는 연결 풀입니다. 클라이언트는 연결을 요청하고 반복자는 지정 연결이 사용 가능한지 확인하고이를 반환합니다. 그렇지 않으면 사용 가능한 연결을 찾을 때까지 반복됩니다.

Python에서 깔끔하게 수행 할 수있는 방법이 있습니까?

답변:


159

를 사용 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'

1
항목을 루프로 인쇄하고 있습니다. 루프를 종료하고 나중에 다시오고 싶은 것은 무엇입니까? (중단 한 부분부터 시작하고 싶습니다).
user443854

7
@ user443854 pool.next()는 사이클에서 단일 다음 항목을 가져 오는 데 사용
Jacob Krall

4
@ user443854 FWIW 이것은 내 것보다 훨씬 더 나은 대답입니다. 라이브러리 함수를 다시 구현할 이유가 없습니다!
Jacob Krall

5
pool.next ()는 나를 위해 작동하지 않았고 next (pool) 만 작동했습니다. 아마도 파이썬 3 때문일까요?
fjsj

6
@fjsj 맞습니다. Python 3에서는 사용해야합니다 next(iterator)(BTW는 Python 2.x에서도 잘 작동하므로 사용해야하는 표준 형식입니다). 참조 파이썬 3.0에서 볼 수의 generator.next을 ()? 더 자세한 설명을 위해. 그에 따라 내 대답을 업데이트했습니다.
Lukas Graf

54

정답은 itertools.cycle 을 사용하는 것 입니다. 그러나 라이브러리 함수가 존재하지 않는다고 가정 해 봅시다. 어떻게 구현 하시겠습니까?

발전기 사용 :

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'
#....

좋은! 목록이 고갈되었을 때 다시 시작하는 것을 어떻게 알 수 있습니까?
user443854

1
@ user443854 while True영원히 반복 하는 수단
Jacob Krall

2
@juanchopanza : 네; itertools.cycle더 나은 대답입니다. itertools사용할 수없는 경우 동일한 기능을 작성하는 방법을 보여줍니다. :)
Jacob Krall

간단한 생성기는 각 요소의 사본도 저장 itertools.cycle합니까? 아니면 단순한 생성기가 더 메모리 효율적인 설계일까요? 당 cycle문서 :Note, this member of the toolkit may require significant auxiliary storage (depending on the length of the iterable).
dthor

2
@dthor이 생성기는 세 가지 요소가 포함 된 목록을 만들고 그에 대한 글을 읽은 다음 목록을 파괴하고 영구적으로 새 목록을 만듭니다. 에 대한 문서 cycle는 입력 iterable이 list생성기가 시작되기 전에 변환된다는 것을 암시합니다 iterable. "값 세트를 한 번만 통과하는 데 적합"하기 때문입니다.
Jacob Krall

9

또는 다음과 같이 할 수 있습니다.

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

abcdefab c를 인쇄합니다 ... 영원히


3

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]

이것을 찬성하는 것은 시작 요소가 한 단계 씩 진행하면서 매번 목록을 여러 번 반복하고자하는 완전히 다른 사용 사례로 저를 도왔습니다. 내 사용 사례는 포커 게임에서 플레이어를 반복하여 딜러가 각 라운드마다 한 명의 플레이어를 앞으로 나아가게하는 것입니다.
Johan

2

사용자 지정 반복자가 필요합니다 . 이 답변 에서 반복자를 적용하겠습니다 .

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

2

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']
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.