2010-05-05 28 views
17

Geriye doğru gitmek için bir python listesi yineleyici yapmak için var mı? bana çıkış verir nedenPython yineleyici yapmak geriye mi gidiyor?

a 
1 
2 
3 
Crap i skipped C 

biliyorum, ancak ben geriye adım bir yolu vardır: Temel olarak

ben bu

class IterTest(object): 
    def __init__(self, data): 
     self.data = data 
     self.__iter = None 

    def all(self): 
     self.__iter = iter(self.data) 
     for each in self.__iter: 
      mtd = getattr(self, type(each).__name__) 
      mtd(each) 

    def str(self, item): 
     print item 

     next = self.__iter.next() 
     while isinstance(next, int): 
      print next 
      next = self.__iter.next() 

    def int(self, item): 
     print "Crap i skipped C" 

if __name__ == '__main__': 
    test = IterTest(['a', 1, 2,3,'c', 17]) 
    test.all() 

çıktıda bu kod sonuçlarını Koşu sahip str() yöntemi, bir adım mı?

DÜZENLEME

Tamam belki bu daha açıklığa kavuşturmak. Tam bir ters yapmak istemiyorum, temel olarak python'da çift yönlü yineleyici eşdeğerini yapmak için kolay bir yol olup olmadığını bilmek istiyorum?

+0

Sadece 'reversed' kullanılarak ne var? Belli bir şekilde geriye doğru gidebilmek mi istiyorsunuz yoksa sadece sonuçları geriye mi almak istiyorsunuz? – jathanism

+1

Oh .... orta tekrarlamayı durdurmak ve yedeklemek mi istiyorsunuz? Büyük olasılıkla, tersine çevirdiğiniz ve 'reversed()' –

+0

kullanarak geçiş yaptığınız listeyi önbelleğe almanız gerekecek, ancak bunu, Icky koduna yol açan, ancak C++ 'da çift yönlü yineleme desteğine sahip olacağız. – UberJumper

cevap

17

Hayır, genel olarak bir Python yineleyicisi geriye doğru gidemezsiniz. Yalnızca geri bir kez anlamak istiyorsanız Ancak, böyle bir şey deneyebilirsiniz:

def str(self, item): 
    print item 

    prev, current = None, self.__iter.next() 
    while isinstance(current, int): 
     print current 
     prev, current = current, self.__iter.next() 

Ardından prev önceki elemanını istediğiniz zaman ulaşabilirsiniz.

Eğer gerçekten bir çift yönlü yineleyici gerekiyorsa, tek kendin uygulayabilirsiniz, ancak yukarıdaki çözümden çok daha yükü tanıtmak olasılığı vardır:

class bidirectional_iterator(object): 
    def __init__(self, collection): 
     self.collection = collection 
     self.index = 0 

    def next(self): 
     try: 
      result = self.collection[self.index] 
      self.index += 1 
     except IndexError: 
      raise StopIteration 
     return result 

    def prev(self): 
     self.index -= 1 
     if self.index < 0: 
      raise StopIteration 
     return self.collection[self.index] 

    def __iter__(self): 
     return self 
+0

Evet, bu durumdan kaçınmaya çalışıyorum, çünkü bu durum biraz can sıkıcı bir yük ekleyecektir:/ – UberJumper

+0

Sorunuzu güncellediğinizi gördüğümden beri bir 'bidirectional_iterator' örneği eklendi, ancak bu muhtemelen olası ilk çözümümden bile daha fazla. –

+0

Bu sınıfın __not__ uygun bir yineleyici ürettiğini unutmayın. Örneklerinde .next() ve .prev() öğelerini manuel olarak çağırabilirsiniz, ancak yinelemenin özelliklerini bir 'for' döngüsünde veya liste anlaşılırlığında geçirme gibi kar elde edemezsiniz. Bu, bir 'TypeError: iter()' bidirectional_iterator 'türünde yinelemesiz döndürdü. – etuardu

3

adımlayıcısı tanım gereği next() yöntemi ile bir nesnedir - - prev()'dan hiç bahsedilmiyor. Bu nedenle, sonuçlarınızı önbelleğe almanız gerekir. Böylece, tekrar ziyaret edebilir veya yineleyicinizi yeniden etkinleştirebilirsiniz, böylece sonuçlarınızın olmasını istediğiniz sırayla döndürür.

3

bir şey eksik ya da bu geriye yineleyici yürümek etmediğini biliyoruz technique described in the Iterator section in the Python tutorial?

>>> class reverse_iterator: 
...  def __init__(self, collection): 
...   self.data = collection 
...   self.index = len(self.data) 
...  def __iter__(self): 
...   return self 
...  def next(self): 
...   if self.index == 0: 
...    raise StopIteration 
...   self.index = self.index - 1 
...   return self.data[self.index] 
...  
>>> for each in reverse_iterator(['a', 1, 2, 3, 'c', 17]): 
...  print each 
... 
17 
c 
3 
2 
1 
a 

kullanamadı ama içinde bunu yapmak için hiçbir yolu yoktur eminim genel. Bunun yerine, ayrık bir koleksiyonu ters sırayla yürüten bir yineleyici yazın. Sorunuzun dayanarak

>>> it = reversed(['a', 1, 2, 3, 'c', 17]) 
>>> type(it) 
<type 'listreverseiterator'> 
>>> for each in it: 
... print each 
... 
17 
c 
3 
2 
1 
a 
+0

Bunun için daha basit ve eşdeğer bir çözüm, tersine çevrilmiş bir sırada bir bağlantı üzerinden yürüyen bir yineleyici döndüren 'tersine çevrilmiş' işlevini kullanmak olacaktır. –

+0

@ Tamás: Düzenlemeyi siz bahsettiğiniz gibi yazıyordum. İlk yanıtı yayınlayana kadar düşünmedim. –

+2

Tüm yineleyiciyi ters çevirmek istemiyorum python içinde iki yönlü bir yineleyicinin eşdeğerini arıyorum. – UberJumper

1

, sizin gibi geliyor: Eğer kendi yazmak zorunda kalmamak için

Düzenleme ayrıca herhangi koleksiyon için bir ters yineleyici almak için reversed() işlevini kullanabilirsiniz böyle bir şey istiyorum: i thi Eğer sorunu çözmek için yardımcı olacağını düşünüyorum

class buffered: 
    def __init__(self,it): 
     self.it = iter(it) 
     self.buf = [] 
    def __iter__(self): return self 
    def __next__(self): 
     if self.buf: 
      return self.buf.pop() 
     return next(self.it) 
    def push(self,item): self.buf.append(item) 

if __name__=="__main__": 
    b = buffered([0,1,2,3,4,5,6,7]) 
    print(next(b)) # 0 
    print(next(b)) # 1 
    b.push(42) 
    print(next(b)) # 42 
    print(next(b)) # 2 
0

class TestIterator(): 
     def __init__(self):` 
      self.data = ["MyData", "is", "here","done"] 
      self.index = -1 
      #self.index=len(self.data)-1 
    def __iter__(self): 
     return self 

    def next(self): 
     self.index += 1 
     if self.index >= len(self.data): 
      raise StopIteration 
     return self.data[self.index] 

    def __reversed__(self): 
     self.index = -1 
     if self.index >= len(self.data): 
      raise StopIteration 
     return self.data[self.index] 

r = TestIterator() 
itr=iter(r) 
print (next(itr)) 
print (reversed(itr)) 
İlgili konular