我不确定最佳策略是什么。我有一个课程,我可以在文件系统中搜索特定模式的文件。我只想执行一次Find.find(“./”)。我将如何处理这:避免在Ruby中对Find.find(“./”)进行多次调用
def files_pattern(pattern)
Find.find("./") do |f|
if f.include? pattern
@fs << f
end
end
end
我不确定最佳策略是什么。我有一个课程,我可以在文件系统中搜索特定模式的文件。我只想执行一次Find.find(“./”)。我将如何处理这:避免在Ruby中对Find.find(“./”)进行多次调用
def files_pattern(pattern)
Find.find("./") do |f|
if f.include? pattern
@fs << f
end
end
end
记住一个方法调用(通常是计算密集型)的结果,这样你就不需要它在下一次重新计算是已知的作为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上解释它。
轻微的变化:你可以改变你的方法来返回所有文件列表,然后使用从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
调用的方法怎么样system "find/-name #{my_pattern}"
如果您想要结果而不是仅仅输出标准输出,请使用返回标记。 – 2010-10-01 12:17:22
这在Windows中肯定会失败,并且在任何其他可能没有找到可用或采用相同参数的平台中都会失败。我只会作为最后一项措施来做到这一点。 – Pablo 2010-10-01 12:34:23
我实际上在发布后立即删除了这个答案(但显然它并没有被删除),但是在我第二次阅读这个问题之后,还有更多的问题。 – 2010-10-01 14:33:25
如果我正确理解你的问题你要运行到Find.find结果分配给一个实例变量。您可以将现在的块移至单独的方法,并调用该方法仅返回与您的模式匹配的文件。
唯一的问题是,如果目录包含很多文件,你在内存中保存一个大数组。
谢谢。我基本上错过了将块转换回方法的观点。 – poseid 2010-10-01 14:11:24
你能否澄清一下这个问题。你是什么意思*只执行Find.find(“./”)一次*? – mikej 2010-10-01 12:32:58
我认为提问者意味着缓存Find.find('./')的结果。 – Swanand 2010-10-01 12:46:04
@Swanand啊,谢谢!在这个基础上我会有一个答案。 – mikej 2010-10-01 13:00:04