2010-10-01 1 views
1

Я не уверен, что является лучшей стратегией для этого. У меня есть класс, где я могу искать файловую систему для определенного шаблона файлов. Я хочу выполнить Find.find ("./") только один раз. как бы я подойти к этому:Избегайте совершать несколько вызовов Find.find ("./") в Ruby

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

Не могли бы вы немного разъяснить вопрос. Что вы подразумеваете под * выполнением Find.find ("./") только один раз *? – mikej

+0

Я думаю, что искатель означает кешировать результат 'Find.find ('./')'. – Swanand

+0

@Swanand ах, спасибо! На этой основе я получаю ответ. – mikej

ответ

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"] 

Примечание: оператор ||= выполняет задание, только если переменная на левой стороне делает принимает значение ложь. то есть @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 
+0

Это нормально, но если теперь я хочу найти первый .xml, то .cpp, .c, .h и я делаю это на большой части файловой системы, я в конечном итоге вызываю Find.find ("./") много раз. Или? – poseid

+0

hm ..Я думаю, мне нужно будет хранить все записи файловой системы в текстовом файле и применять класс Finder к текстовому файлу, который должен быть быстрее, чем find() каждый раз, конечно, я должен обновить текстовый файл до того, как я сделаю фильтрацию. – poseid

+0

@poseid Я добавил вариант в конец ответа. Посмотрите, действительно ли это полезно. – mikej

-2

как о system "find/-name #{my_pattern}"

+1

используйте обратные тики, если вы хотите, чтобы результаты вместо него просто собирались на stdout. –

+0

Это наверняка провалится в Windows и на любой другой платформе, которая может не найти доступ или использовать одни и те же параметры. Я сделал бы это только как последнюю меру. – Pablo

+0

Я действительно удалил этот ответ сразу после публикации (но, видимо, он не удалялся). Bc есть больше проблем с ним, чем упоминалось после того, как я прочитал этот вопрос во второй раз. –

1

Если я правильно понимаю ваш вопрос вы хотите запустить Find.find, чтобы присвоить результат переменной экземпляра. Вы можете переместить то, что теперь является блоком для отдельного метода, и вызвать это, чтобы возвращать только файлы, соответствующие вашему шаблону.

Проблема только в том, что если каталог содержит много файлов, вы храните большой массив в памяти.

+0

спасибо. я в основном пропустил точку, чтобы перевести блок обратно в метод. – poseid

 Смежные вопросы

  • Нет связанных вопросов^_^