2012-04-22 18 views
8

Bir birincil dizeden n öğelerinden fazla öğe içeren belirli bir uzunluktaki alt dizeleri her benzersiz bileşimini içeren bir üreteç döndürmek için bir işlev yazdım. Bir örnek olarak Python'daki Yinelemeli Jeneratörler

:

i elde etmek istiyorum 'abcdefghi' ve iki uzunluğunun bir prob ve liste başına 4 elemanlarının bir eşik varsa:

['ab', 'cd', 'ef', 'gh'] 
['ab', 'de', 'fg', 'hi'] 
['bc', 'de', 'fg', 'hi'] 

İlk Bu soruna teşebbüs bir liste listesini döndürmeyi içeriyordu. Bu bilgisayarın belleğini taşan sona erdi. Ham ikincil bir çözüm olarak, benzer bir şey yapan bir jeneratör oluşturdum. Sorun şu ki, kendisini çağıran iç içe geçmiş bir jeneratör oluşturdum. Bu işlevi çalıştırdığımda, aslında kendini tekrar aramaksızın iç döngü etrafında dönüyor gibi görünüyor. Bir jeneratörün, verim beyanına varana kadar gerekli olduğu kadar tekrarlama deliğinden aşağı doğru ilerleyeceğini düşündüm. Ne olduğu hakkında bir ipucu var mı?

def get_next_probe(self, current_probe_list, probes, unit_length): 
    if isinstance(current_probe_list, list): 
     last_probe=current_probe_list[-1] 
     available_probes = [candidate for candidate in probes if candidate.start>last_probe.end] 
    else: 
     available_probes = [candidate for candidate in probes if candidate.start<unit_length] 

    if available_probes: 

     max_position=min([probe.end for probe in available_probes]) 
     available_probes2=[probe for probe in available_probes if max_position+1>probe.start] 

     for new_last_probe in available_probes2: 
      new_list=list(current_probe_list) 
      new_list.append(new_last_probe) 
      self.get_next_probe(new_list, probes, unit_length) 

    else: 
     if len(current_probe_list)>=self.num_units: 
      yield current_probe_list 

Verim yazdırılacak şekilde değiştirilirse, bu işlem düzgün çalışır! Alabileceğim herhangi bir yardım için minnettar olurum. Bunun, bu tür bir arama sorununun optimal bir uygulaması olmadığını anlıyorum, get_next_probe'nin son çağrısından bulunan bir konum listesine geri dönmek ve new_last_probe.end ile örtüşmeyen öğeler için bu listeyi filtrelemek çok daha verimli olurdu ... ama bu benim yazmam için çok daha kolaydı. Herhangi bir algoritma girişi hala takdir edilecektir.

Teşekkürler!

+2

don Yinelemeli aramanızdan gelen sonucu kullanıyor gibi görünmüyor. Dış listenin bir alt kısmı üzerinde yinelenen bir iç döngü görmeyi beklerim, sonucu elde edilen sonucu oluşturmak için bir özyinelemeli çağrının sonucunu birleştirir. –

+0

İlk satırda bir alıntı kaçırıyorsunuz, ab, çok –

cevap

17

Ben, bu verim deyimi

Bu ince recurse, ancak dışa geri yayılmasının yield ed değeri elde etmek çarpana kadar bir jeneratör gerektiği kadar tekrarlama delikte kadarıyla önüne düşünüyordu Bunu açıkça yapmanız gerekir - tıpkı bir return gibi, her yinelemenin sonucu olarak açıkça return gerekir. Yani bunun yerine: Python 3.3 veya daha yeni kullanıyorsanız, ayrıca bunu yapabilirsiniz Veya

for val in self.get_next_probe(new_list, probes, unit_length): 
    yield val 

:

self.get_next_probe(new_list, probes, unit_length) 

Sen böyle bir şey yapsın

yield from self.get_next_probe(new_list, probes, unit_length) 
+3

Python 3.2'den başlayarak, sadece 'self.get_next_prob (...) 'öğesinden get verebilirsiniz. – Dougal

+1

@Dougal, 'verim 3.2 değil, ancak çıktığında 3,3 olacak. – lvc

+0

İyi nokta @Ivc ... bunu söylemeden önce kontrol edebilirdim, çünkü kodlarımın çoğunu bu günlerde zaten 3.2. :) – Dougal