我不确定什么是最好的策略。我有一堂课,我可以在文件系统中搜索特定模式的文件。我只想执行一次 Find.find("./") 。我将如何处理这个:
def files_pattern(pattern)
Find.find("./") do |f|
if f.include? pattern
@fs << f
end
end
end
记住方法调用的(通常是计算密集型的)结果,以便下次调用该方法时不需要重新计算它,这称为记忆化,因此您可能需要阅读更多相关信息。
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 时,运算符才会执行赋值。ie是由于短路评估而第一次调用where@matches ||= find_matches
的简写。Stackoverflow 上还有很多其他问题对此进行了解释。@matches = @matches || find_matches
find_matches
细微的变化:您可以更改方法以返回所有文件的列表,然后使用Enumerable
诸如grep
和select
的方法对同一文件列表执行多次搜索。当然,这样做的缺点是将整个文件列表保存在内存中。这是一个例子:
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
如果我正确理解您的问题,您希望运行 Find.find 将结果分配给实例变量。您可以将现在的块移动到单独的方法并调用它以仅返回与您的模式匹配的文件。
唯一的问题是,如果目录包含许多文件,则您在内存中持有一个大数组。
怎么样system "find / -name #{my_pattern}"