2009-08-31 6 views
1

Le titre n'explique vraiment pas les choses. Ma situation est que je voudrais lire un fichier et mettre le contenu dans un hachage. Maintenant, je veux le rendre intelligent, je veux créer une boucle qui ouvre chaque fichier dans un répertoire et le mettre dans un hachage. Le problème est que je ne sais pas comment attribuer un nom par rapport au nom du fichier. par exemple:Comment assigner de nouveaux noms de variables quand il est déjà assigné à quelque chose? Ruby

hash={} 
Dir.glob(path + "*") do |datafile| 
    file = File.open(datafile) 
    file.each do |line| 
    key, value = line.chomp("\t") 
    # Problem here is that I wish to have a different 
    # hash name for every file I loop through 
    hash[key]=value 
    end 
    file.close 
end 

Est-ce possible?

+0

Que diriez-vous d'un hachage de hachages. avec le premier hachage ayant des clés étant les noms de fichiers? Cela fonctionnerait-il? – theIV

+0

Ah, je vois des gens qui me battent dessus! :) – theIV

Répondre

1

Vous souhaitez créer dynamiquement des variables avec les noms des fichiers que vous traitez?

essayez ceci:

Dir.glob(path + "*") do |fileName| 
    File.open(fileName) { 

    # the variable `hash` and a variable named fileName will be 
    # pointing to the same object... 
    hash = eval("#{fileName} = Hash.new") 

    file.each do |line| 
     key, value = line.chomp("\t") 
     hash[key]=value 
    end 
    } 
end 

Bien sûr, vous devez vous assurer que vous rubify le nom du fichier en premier. Une variable nommée "bla.txt" ne serait pas valable en rubis, ni ne "path/to/bla.csv"

+0

+1 pour résoudre le problème de la manière demandée – bobDevil

+0

Notez cependant que vous ne serez pas en mesure d'accéder aux nouvelles variables sans eval. De même, les noms de fichiers contenant des espaces ou des citations (entre autres choses) briseraient cette approche. – sepp2k

+1

Je ne suis pas sûr que "résoudre le fichier de la manière demandée" est nécessairement une vertu. Si le questionneur en savait assez pour être certain du meilleur moyen, il ne serait probablement pas là. – Chuck

0

Ne pouvez-vous pas faire ce qui suit?

filehash = {} # after the File.open line 

... 
# instead of hash[key] = value, next two lines 
hash[datafile] = filehash 
filehash[key] = value 
0

Vous voudrez peut-être utiliser quelque chose comme ceci:

hash[file] = {} 
hash[file][key] = value
8

Pourquoi n » t vous utilisez un hash dont les clés sont les noms de fichiers (dans votre cas "datafile") et dont la valeur sont des hashes dans lesquels vous insérez vos données?

hash = Hash.new { |h, key| h[key] = Hash.new } 
Dir.glob(path + '*') do |datafile| 
    next unless File.stat(datafile).file? 
    File.open(datafile) do |file| 
    file.each do |line| 
     key, value = line.split("\t") 
     puts key, value 
     # Different hash name for every file is now hash[datafile] 
     hash[datafile][key]=value 
    end 
    end 
end 
+2

Vous pouvez remplacer 'File.open' et' file.each' par 'File.foreach (fichier de données) do | line |' – sepp2k

1

Si vous voulez créer une variable dynamique, vous pouvez également utiliser #instance_variable_set (en supposant que les variables d'instance sont également OK.

Dir.glob(path + "*") do |datafile|    
    file = File.open(datafile)      
    hash = {}          
    file.each do |line|        
    key, value = line.chomp("\t")     
    hash[key] = value        
    end            
    instance_variable_set("@file_#{File.basename(datafile)}", hash)  
end 

Cela ne fonctionne que lorsque le nom de fichier est un nom de variable Ruby valide . Sinon, vous avez besoin d'une transformation

0

Deux hash est maintenant assez fileHash -..> lineHash -> contenu

Questions connexes