2014-05-01 15 views
38

Tôi cần lặp qua danh sách vòng tròn, có thể nhiều lần, mỗi lần bắt đầu với mục được truy cập lần cuối.Trình vòng lặp danh sách tròn trong Python

Trường hợp sử dụng là một hồ bơi kết nối. Một máy khách yêu cầu kết nối, một trình vòng lặp kiểm tra xem kết nối được trỏ tới có sẵn và trả về nó hay không, nếu không thì vòng lặp cho đến khi nó tìm thấy kết nối có sẵn.

Có cách nào gọn gàng để làm điều đó bằng Python không?

+0

Bạn có thể đăng một số mã mẫu của những gì bạn có và những gì bạn đã thử? – wnnmaw

Trả lời

73

Sử dụng itertools.cycle, đó là mục đích chính xác của nó:

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 mãi mãi, rõ ràng)


Để bằng tay thúc đẩy các iterator và kéo giá trị từ nó từng người một, chỉ cần gọi next(pool):

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

Bạn đang in các mục trong một vòng lặp. Tôi muốn rời khỏi vòng lặp và quay lại sau? (Tôi muốn bắt đầu từ nơi tôi rời đi). – user443854

+3

@ user443854 sử dụng 'pool.next()' để lấy một mục tiếp theo từ chu kỳ –

+0

Điều gì @JacobKrall nói ;-) Bạn có thể "thủ công" chuyển tiếp bất kỳ trình lặp nào bằng cách gọi 'iterator.next()' trên đó. Đó là cơ bản những gì một vòng lặp 'for' làm cho bạn. –

29

Câu trả lời đúng là sử dụng itertools.cycle. Tuy nhiên, giả sử rằng chức năng thư viện không tồn tại. Làm thế nào bạn sẽ thực hiện nó?

Sử dụng một generator:

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

Sau đó, bạn có thể sử dụng một tuyên bố for để lặp vô hạn, hoặc bạn có thể gọi next() để có được những giá trị tiếp theo duy nhất từ ​​iterator máy phát điện:

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

Rất tuyệt! Làm sao nó biết để bắt đầu lại khi danh sách bị cạn kiệt? – user443854

+1

@ user443854 the 'while True' có nghĩa là lặp lại mãi mãi –

+0

@juanchopanza: Yep; 'itertools.cycle' là một câu trả lời tốt hơn. Điều này cho thấy cách bạn có thể viết cùng chức năng nếu 'itertools' không có sẵn :) –

1

Bạn cần trình lặp lặp tùy chỉnh - Tôi sẽ điều chỉnh trình lặp từ 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 
2

Hoặc bạn có thể làm như thế này:

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

in a b c d e f a b c ...mãi mãi

1

bạn có thể thực hiện điều này với append(pop()) loop:

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

hoặc for i in range() loop:

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

hoặc đơn giản là:

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

while 1: 
    for i in l: 
     print i 

tất cả đều in:

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

của ba tôi sẽ dễ bị các phương pháp append (pop()) là một hàm

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

Nếu bạn muốn chu kỳ n lần, thực hiện ncyclesitertools recipe:

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'] 
Các vấn đề liên quan