पायथन में परिपत्र सूची पुनरावृत्त


99

मुझे एक गोलाकार सूची पर पुनरावृति करने की आवश्यकता है, संभवतः कई बार, पिछली बार देखी गई वस्तु से शुरू होने वाली हर बार।

उपयोग मामला एक कनेक्शन पूल है। एक क्लाइंट कनेक्शन के लिए पूछता है, एक इट्रेटर चेक करता है कि क्या पॉइंट-टू कनेक्शन उपलब्ध है और इसे वापस करता है, अन्यथा जब तक यह उपलब्ध नहीं होता है तब तक लूप करता है।

क्या पायथन में इसे करने का एक साफ तरीका है?

जवाबों:


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()को चक्र से एकल अगला आइटम प्राप्त करने के लिए उपयोग करें
याकूब

4
@ user443854 FWIW यह मेरा से बेहतर जवाब है। पुस्तकालय कार्यों को फिर से लागू करने के लिए जाने का कोई कारण नहीं!
जैकब क्राल

5
pool.next () ने मेरे लिए काम नहीं किया, केवल अगले (पूल)। शायद पायथन 3 की वजह से?
fjsj

6
@fjsj जो सही है, पायथन 3 पर आपको उपयोग करने की आवश्यकता है next(iterator)(जो कि BTW भी ​​पायथन 2.x पर ठीक काम करता है, और इसलिए विहित रूप है जिसका उपयोग किया जाना चाहिए)। देखें Is generator.next () अजगर 3.0 में दिखाई दे रहा? अधिक गहराई से स्पष्टीकरण के लिए। तदनुसार मेरा उत्तर अपडेट करें।
लुकास ग्राफ

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हमेशा के लिए दोहराने का साधन
याकूब

2
@ जुआनचोपान्ज़ा: हां; itertools.cycleएक बेहतर जवाब है। यह दिखाता है कि यदि आप itertoolsउपलब्ध नहीं हैं तो आप एक ही कार्यक्षमता कैसे लिख सकते हैं :)
याकूब क्राल

क्या साधारण जनरेटर भी प्रत्येक तत्व की एक प्रति को बचाता itertools.cycleहै? या साधारण जनरेटर एक अधिक स्मृति-कुशल डिजाइन होगा? प्रति cycleडॉक्स :Note, this member of the toolkit may require significant auxiliary storage (depending on the length of the iterable).
dthor

2
@ यह जनरेटर तीन तत्वों के साथ एक सूची बनाता है और इस पर साक्षर करता है, फिर सूची को नष्ट करता है और एक नया बनाता है, सदा में। इसका cycleअर्थ यह है कि इनपुट जेनरेट listहोने से पहले इसका जनरेटर में बदलने का मतलब है , क्योंकि iterableयह केवल "मूल्यों के सेट पर एक पास के लिए अच्छा" है।
जैकब क्राल

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.

तीन मैं एक समारोह के रूप में परिशिष्ट (पॉप ()) दृष्टिकोण के लिए प्रवण हो जाएगा

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]

इसे आगे बढ़ाते हुए क्योंकि इससे मुझे एक पूरी तरह से अलग उपयोग के मामले में मदद मिली, जहां मैं बस एक सूची में कई बार पुनरावृति करना चाहता हूं, हर बार प्रारंभ तत्व के साथ एक कदम आगे बढ़ाना। मेरा उपयोग मामला पोकर के एक खेल में खिलाड़ियों पर पुनरावृत्ति करना है, जिससे प्रत्येक गोल के लिए डीलर एक खिलाड़ी को आगे बढ़ाता है।
जोहान

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 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']
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.