2010-10-01 28 views
1

我不確定最佳策略是什麼。我有一個課程,我可以在文件系統中搜索特定模式的文件。我只想執行一次Find.find(「./」)。我將如何處理這:避免在Ruby中對Find.find(「./」)進行多次調用

def files_pattern(pattern) 
    Find.find("./") do |f| 
     if f.include? pattern 
      @fs << f 
     end 
    end 
    end 
+0

你能否澄清一下這個問題。你是什​​麼意思*只執行Find.find(「./」)一次*? – mikej 2010-10-01 12:32:58

+0

我認爲提問者意味着緩存Find.find('./')的結果。 – Swanand 2010-10-01 12:46:04

+0

@Swanand啊,謝謝!在這個基礎上我會有一個答案。 – mikej 2010-10-01 13:00:04

回答

4

記住一個方法調用(通常是計算密集型)的結果,這樣你就不需要它在下一次重新計算是已知的作爲memoization所以你可能會想要閱讀更多關於這一點。

實現它的一種方式是,Ruby將使用將結果存儲在實例變量中的小封裝類。例如

class Finder 
    def initialize(pattern) 
    @pattern = pattern 
    end 

    def matches 
    @matches ||= find_matches 
    end 

    private 

    def find_matches 
    fs = [] 
    Find.find("./") do |f| 
     if f.include? @pattern 
     fs << f 
     end 
    end 
    fs 
    end 
end 

然後你就可以這樣做:

irb(main):089:0> f = Finder.new 'xml' 
=> #<Finder:0x2cfc568 @pattern="xml"> 
irb(main):090:0> f.matches 
find_matches 
=> ["./example.xml"] 
irb(main):091:0> f.matches # won't result in call to find_matches 
=> ["./example.xml"] 

注:||=操作執行只有在左側的變量不計算爲False分配。即@matches ||= find_matches@matches = @matches || find_matches的簡寫,其中find_matches將僅由於短路評估而被首次調用。有很多other questions在Stackoverflow上解釋它。


輕微的變化:你可以改變你的方法來返回所有文件列表,然後使用從Enumerablegrepselect方法來對文件的同一列表進行多次搜尋。當然,這存在將整個文件列表保存在內存中的缺點。這裏雖然是一個例子:

def find_all 
    fs = [] 
    Find.find("./") do |f| 
    fs << f 
    end 
    fs 
end 

,然後用它喜歡:

files = find_all 
files.grep /\.xml/ 
files.select { |f| f.include? '.cpp' } 
# etc 
+0

這是可以的,但如果我現在想要找到第一個.xml,然後.cpp,.c,.h,並且我在文件系統的大部分上執行此操作,我最終調用Find.find(「./」 ) 多次。要麼? – poseid 2010-10-01 13:34:56

+0

hm ..我想我需要將文件系統的所有條目存儲在文本文件中,並將Finder類應用於文本文件,每次都應該比find()更快,因爲我必須在過濾之前更新文本文件。 – poseid 2010-10-01 13:48:50

+0

@poseid我在答案的末尾添加了一個變體。看看這是否有用。 – mikej 2010-10-01 13:54:02

-2

調用的方法怎麼樣system "find/-name #{my_pattern}"

+1

如果您想要結果而不是僅僅輸出標準輸出,請使用返回標記。 – 2010-10-01 12:17:22

+0

這在Windows中肯定會失敗,並且在任何其他可能沒有找到可用或採用相同參數的平臺中都會失敗。我只會作爲最後一項措施來做到這一點。 – Pablo 2010-10-01 12:34:23

+0

我實際上在發佈後立即刪除了這個答案(但顯然它並沒有被刪除),但是在我第二次閱讀這個問題之後,還有更多的問題。 – 2010-10-01 14:33:25

1

如果我正確理解你的問題你要運行到Find.find結果分配給一個實例變量。您可以將現在的塊移至單獨的方法,並調用該方法僅返回與您的模式匹配的文件。

唯一的問題是,如果目錄包含很多文件,你在內存中保存一個大數組。

+0

謝謝。我基本上錯過了將塊轉換回方法的觀點。 – poseid 2010-10-01 14:11:24