2009-06-30 26 views
17

Ben Ruby için biraz yeni ve çok sezgisel bir dil olmasına rağmen örtük dönüş değerlerinin nasıl davrandığını anlamakta zorluk çekiyorum.Ruby'de gizli dönüş değerleri

Tomcat günlüklerini greplemek ve ilgili verilerden boruya ayrılmış CSV dosyaları oluşturmak için küçük bir program üzerinde çalışıyorum. İşte bir günlük girişinden satırları oluşturmak için kullanıyorum basitleştirilmiş bir örnek. Bu kodu çalıştırdığınızda

class LineMatcher 
    class << self 
    def match(line, regex) 
     output = "" 
     line.scan(regex).each do |matched| 
     output << matched.join("|") << "\n" 
     end 
     return output 
    end   
    end 
end 


puts LineMatcher.match("00:00:13,207 06/18 INFO stateLogger - TerminationRequest[[email protected][accountNumber=0951714636005,srNumber=20]", 
         /^(\d{2}:\d{2}:\d{2},\d{3}).*?(\d{2}\/\d{2}).*?\[accountNumber=(\d*?),srNumber=(\d*?)\]/) 

Ben açıkça output değerini döndürürken beklenen budur aşağıdakileri, geri gel. Ben şu şekilde LineMatcher değiştirip açıkça dönmemesi halinde

00:00:13,207|06/18|0951714636005|20 

Ancak çıkışı: Sonra

class LineMatcher 
     class << self 
     def match(line, regex) 
      output = "" 
      line.scan(regex).each do |matched| 
      output << matched.join("|") << "\n" 
      end 
     end   
     end 
    end 

ben şu sonucu alırsınız: Açıkçası

00:00:13,207 
06/18 
0951714636005 
20 

bu değil istenen sonuç. Çıkış değişkeninden kurtulmam gerektiği gibi geliyor, ancak dönüş değerinin nereden geldiği belli değil. Ayrıca, okunabilirlik için diğer öneriler/geliştirmeler memnuniyetle karşılıyor.

+0

Düzeltilmiş biçimlendirme – csamuel

cevap

23

yakut bulunan herhangi bir ifade geçen değerlendirilen ifadenin değerini döndürür (bu durumda) daha okunabilir açık dönüşü ile yöntemini bulmak .. benden daha iyi açıklayabilir . Programınızın nasıl hareket edeceğini tam olarak bilmek için en çok kullanılan yöntemin uygulanmasını ve davranışını bilmeniz gerekir.

#each, yinelediğiniz koleksiyonu döndürür. Yani, aşağıdaki kod, line.scan (regexp) değerini döndürecektir. Eğer yürütme sonucunu dönmek isterseniz

line.scan(regex).each do |matched| 
    output << matched.join("|") << "\n" 
end 

, sen each olarak çalışıyor fakat değiştirilmiş koleksiyonunu döndürür map kullanabilirsiniz.

class LineMatcher 
    class << self 
    def match(line, regex) 
     line.scan(regex).map do |matched| 
     matched.join("|") 
     end.join("\n") # remember the final join 
    end   
    end 
end 

Özel durumunuza bağlı olarak kullanabileceğiniz birkaç yararlı yöntem vardır. Bu durumda,'u scan tarafından döndürülen sonuç sayısı yüksek değilse (diziler üzerinde çalışıp bunları birleştirmek, tek bir dizede çalışmaktan daha verimlidir) kullanmak isteyebilirsiniz.

class LineMatcher 
    class << self 
    def match(line, regex) 
     line.scan(regex).inject("") do |output, matched| 
     output << matched.join("|") << "\n" 
     end 
    end   
    end 
end 
+2

Geri bildiriminiz için teşekkürler ... Sanırım kafa karışıklığım, aslında son ifade olarak yorumlanıp neyin yorumlandığını söylemek zordu. – csamuel

13

Ruby'de bir yöntemin dönüş değeri, son ifadeyle döndürülen değerdir. Açık bir dönüşü de tercih edebilirsiniz.

Örneğinizde, ilk parçacık output dizesini döndürür. Ancak ikinci snippet, eşleşme dizisi olduğu ortaya çıkan each yöntemiyle (şimdi son stmt olan) döndürülen değeri döndürür.

irb(main):014:0> "StackOverflow Meta".scan(/[aeiou]\w/).each do |match| 
irb(main):015:1* s << match 
irb(main):016:1> end 
=> ["ac", "er", "ow", "et"] 

Güncelleme: Ancak yine de tek bir satır üzerinde çıktı açıklamaz. Biçimlendirme hatası olduğunu düşünüyorum, eşleşmelerin her birini farklı bir satıra yazdırmalı çünkü bu şekilde puts bir dizi basıyor. Biraz kod

irb(main):003:0> one_to_three = (1..3).to_a 
=> [1, 2, 3] 
irb(main):004:0> puts one_to_three 
1 
2 
3 
=> nil 

Şahsen ben

+1

Üzgünüm, evet, bir biçimlendirme hatası vardı. Soruya göre düzeltildi. – csamuel