1

我不确定什么是最好的策略。我有一堂课,我可以在文件系统中搜索特定模式的文件。我只想执行一次 Find.find("./") 。我将如何处理这个:

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

3 回答 3

4

记住方法调用的(通常是计算密集型的)结果,以便下次调用该方法时不需要重新计算它,这称为记忆化,因此您可能需要阅读更多相关信息。

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_matchesfind_matches


细微的变化:您可以更改方法以返回所有文件的列表,然后使用Enumerable诸如grepselect的方法对同一文件列表执行多次搜索。当然,这样做的缺点是将整个文件列表保存在内存中。这是一个例子:

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
于 2010-10-01T13:04:37.780 回答
1

如果我正确理解您的问题,您希望运行 Find.find 将结果分配给实例变量。您可以将现在的块移动到单独的方法并调用它以仅返回与您的模式匹配的文件。

唯一的问题是,如果目录包含许多文件,则您在内存中持有一个大数组。

于 2010-10-01T13:51:44.487 回答
-2

怎么样system "find / -name #{my_pattern}"

于 2010-10-01T12:16:42.450 回答