2010-10-01 2 views
1

Je ne sais pas quelle est la meilleure stratégie pour cela. J'ai une classe, où je peux rechercher le système de fichiers pour un certain modèle de fichiers. Je veux exécuter Find.find ("./") seulement une fois. comment pourrais-je approche ceci:Éviter de faire plusieurs appels à Find.find ("./") dans Ruby

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

Pouvez-vous clarifier un peu la question? Que voulez-vous dire par * exécuter Find.find ("./") seulement une fois *? – mikej

+0

Je pense que le demandeur veut mettre en cache le résultat de 'Find.find ('./')'. – Swanand

+0

@Swanand ah, merci! Je vais essayer de répondre à cette question. – mikej

Répondre

4

Se souvenir du résultat (habituellement de calculs) d'un appel de méthode afin que vous ne avez pas besoin de recalculer la prochaine fois que la méthode est appelée est connue comme memoization donc vous voudrez probablement en savoir plus à ce sujet.

Une façon de réaliser que Ruby est d'utiliser une petite classe wrapper qui stocke le résultat dans une variable d'instance. par exemple.

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 

Et vous pouvez faire:

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

Note: l'opérateur effectue une mission ||= que si la variable du côté gauche fait la valeur false. c'est-à-dire @matches ||= find_matches est un raccourci pour @matches = @matches || find_matchesfind_matches ne sera appelée que la première fois en raison d'une évaluation de court-circuit. Il y a beaucoup de other questions qui l'expliquent sur Stackoverflow.


légère variation: Vous pouvez changer votre méthode pour retourner une liste de tous les fichiers et utiliser des méthodes de Enumerable telles que grep et select pour effectuer des recherches multiples sur la même liste de fichiers. Bien sûr, cela a l'inconvénient de garder toute la liste des fichiers en mémoire. Voici cependant un exemple:

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

Et utilisez-le comme:

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

c'est OK, mais si je veux maintenant trouver le .xml d'abord, puis .cpp, .c, .h et je le fais sur une grande partie du système de fichiers, je finis par appeler Find.find ("./") plusieurs fois. Ou? – poseid

+0

hm ..Je pense que je devrais stocker toutes les entrées du système de fichiers dans un fichier texte, et appliquer la classe Finder au fichier texte, qui devrait être plus rapide que trouver() à chaque fois, bien sûr, je dois mettre à jour le fichier texte avant de faire le filtrage. – poseid

+0

@poseid J'ai ajouté une variante à la fin de la réponse. Voyez si c'est utile du tout. – mikej

-2

que diriez-vous system "find/-name #{my_pattern}"

+1

utiliser les tics de retour si vous voulez que les résultats au lieu de cela vont simplement à stdout. –

+0

Cela échouerait dans Windows à coup sûr et dans toute autre plate-forme qui pourrait ne pas avoir trouvé disponible ou prendre les mêmes paramètres. Je le ferais seulement comme la dernière mesure. – Pablo

+0

J'ai effectivement supprimé cette réponse immédiatement après l'affichage (mais apparemment il n'a pas été supprimé) bc il ya plus de problèmes avec ce que mentionné après avoir lu la question une deuxième fois. –

1

Si je comprends bien votre question que vous voulez exécuter Find.find pour affecter le résultat à une variable d'instance. Vous pouvez déplacer ce qui est maintenant le bloc vers une méthode séparée et l'appeler pour retourner uniquement les fichiers correspondant à votre modèle.

Seul problème est que si le répertoire contient beaucoup de fichiers, vous détenez un grand tableau en mémoire.

+0

merci. J'ai fondamentalement raté le point de traduire le bloc en une méthode. – poseid

Questions connexes