2016-01-25 4 views
0

I ont un hachage de paires de valeurs clés, similaire à -Ruby - Initialiser a la valeur clé dans une boucle

myhash={'test1' => 'test1', 'test2 => 'test2', ...} 

comment puis-je initialiser une telle table de hachage dans une boucle? Fondamentalement, j'en ai besoin pour aller de 1.50 avec les mêmes valeurs $ i de test mais je n'arrive pas à comprendre comment l'initialiser correctement dans une boucle au lieu de le faire manuellement. Je sais comment parcourir chaque paire clé-valeur individuelle:

myhash.each_pair do |key, value| 

mais cela ne suffit pas init

+0

Votre hachage est invalide. – sawa

Répondre

4

Que diriez-vous:

hash = (1..50).each.with_object({}) do |i, h| 
    h["test#{i}"] = "test#{i}" 
end 

Si vous voulez Faites ceci paresseusement, vous pourriez faire quelque chose comme ci-dessous:

hash = Hash.new { |hash, key| key =~ /^test\d+/ ? hash[key] = key : nil} 
p hash["test10"] 
#=> "test10" 
p hash 
#=> {"test10"=>"test10"} 

Le bloc passé à Hash constructeur sera invoqué chaque fois qu'une clé n'est pas trouvée dans le hachage, nous vérifions si la clé suit un certain modèle (en fonction de vos besoins), et créons une paire clé-valeur dans hachage où valeur est égale à clé passé.

2

Tout d'abord, il y a Array#to_h, qui convertit un tableau de paires clé-valeur en un hachage.

Deuxièmement, vous pouvez simplement initialiser un hachage dans une boucle, il suffit de faire quelque chose comme ceci:

target = {} 
1.upto(50) do |i| 
    target["test_#{i}"] = "test_#{i}" 
end 
4
(1..50).map { |i| ["test#{i}"] * 2 }.to_h 

La solution ci-dessus est plus sec que deux autres réponses, puisque "test" n'est pas répété deux fois :)

Il est BTW, environ 10% plus rapide (ce ne serait pas un cas où les clés et les valeurs sont différentes):

require 'benchmark' 
n = 500000 
Benchmark.bm do |x| 
    x.report { n.times do ; (1..50).map { |i| ["test#{i}"] * 2 }.to_h ; end } 
    x.report { n.times do ; (1..50).each.with_object({}) do |i, h| ; h["test#{i}"] = "test#{i}" ; end ; end } 
end 

    user  system  total  real 
17.630000 0.000000 17.630000 (17.631221) 
19.380000 0.000000 19.380000 (19.372783) 

Ou on peut utiliser eval:

hash = {} 
(1..50).map { |i| eval "hash['test#{i}'] = 'test#{i}'" } 

ou même JSON#parse:

require 'json' 
JSON.parse("{" << (1..50).map { |i| %Q|"test#{i}": "test#{i}"| }.join(',') << "}") 
+1

'* 2' est génial, même si c'est un peu obscur – mgarciaisaia

+0

Ne fonctionnera que s'il est supposé que la clé et la valeur commencent par la même chaîne (c'est-à-dire' test'). –

+0

@WandMaker En effet. Mais changer '[" test # {i} "] * 2' en' ["test # {i}", "quest # {i}"] 'n'est pas une science de fusée. – mudasobwa

1

Vous pouvez aussi le faire:

hash = Hash.new{|h, k| h[k] = k.itself} 
(1..50).each{|i| hash["test#{i}"]} 
hash # => ... 
+0

Cela produit apparemment le hachage, qui se comporte légèrement différente. Je crois que OP ne s'attend pas à ce que le hachage retourne une valeur sur n'importe quelle clé. – mudasobwa

+0

@mudasobwa La différence ne provoquerait pas de différence de comportement à moins que l'OP n'appelle le hachage avec une clé indéfinie. Mais si c'est toujours un problème, alors le proc par défaut peut être enlevé après avoir créé le hachage. – sawa