web-dev-qa-db-fra.com

Comment changer toutes les clés d'un hachage par un nouvel ensemble de clés données

Comment changer toutes les clés d'un hachage par un nouvel ensemble de clés données?

Y a-t-il un moyen de le faire avec élégance?

47
JCLL

Ruby 2.5 a hachage # Transform_keys! Méthode. Exemple Utilisation d'une carte des clés

h = {a: 1, b: 2, c: 3}
key_map = {a: 'A', b: 'B', c: 'C'}

h.transform_keys! {|k| key_map[k]}
# => {"A"=>1, "B"=>2, "C"=>3} 

Vous pouvez également utiliser le symbole # TOPROC Raccourci avec Transform_Keys, par exemple:

h.transform_keys! &:upcase
# => {"A"=>1, "B"=>2, "C"=>3}
10
Santhosh

En supposant que vous ayez un Hash qui mesure les anciennes clés des nouvelles clés, vous pouvez faire quelque chose comme

hsh.map {|k, v| [key_map[k], v] }.to_h
77
Jörg W Mittag

je suppose que vous voulez changer le hasch keys sans modifier les valeurs:

hash = {
   "nr"=>"123",
   "name"=>"Herrmann Hofreiter",
   "pferd"=>"010 000 777",
   "land"=>"hight land"
}
header = ["aa", "bb", "cc", "dd"]
new_hash = header.Zip(hash.values).to_h

Résultat:

{
   "aa"=>"123",
   "bb"=>"Herrmann Hofreiter",
   "cc"=>"010 000 777",
   "dd"=>"high land"
}
3
Kiry Meas

Une autre façon de le faire est:

hash = {
  'foo' => 1,
  'bar' => 2
}

new_keys = {
  'foo' => 'foozle',
  'bar' => 'barzle'
}

new_keys.values.Zip(hash.values_at(*new_keys.keys)).to_h 
# => {"foozle"=>1, "barzle"=>2}

Le briser:

new_keys
.values # => ["foozle", "barzle"]
.Zip(
  hash.values_at(*new_keys.keys) # => [1, 2]
) # => [["foozle", 1], ["barzle", 2]]
.to_h 
# => {"foozle"=>1, "barzle"=>2}

C'est une référence de référence ...

Bien que j'aime la simplicité de la réponse de Jörn, je n'étais pas sûr que c'était aussi vite que cela devrait être, puis j'ai vu le commentaire de Selvamani:

require 'fruity'

HASH = {
  'foo' => 1,
  'bar' => 2
}

NEW_KEYS = {
  'foo' => 'foozle',
  'bar' => 'barzle'
}

compare do
  mittag    { HASH.dup.map {|k, v| [NEW_KEYS[k], v] }.to_h }
  ttm       { h = HASH.dup; NEW_KEYS.values.Zip(h.values_at(*NEW_KEYS.keys)).to_h }
  selvamani { h = HASH.dup; h.keys.each { |key| h[NEW_KEYS[key]] = h.delete(key)}; h }
end

# >> Running each test 2048 times. Test will take about 1 second.
# >> selvamani is faster than ttm by 39.99999999999999% ± 10.0%
# >> ttm is faster than mittag by 10.000000000000009% ± 10.0%

Celles-ci fonctionnent très près de la vitesse de vitesse, de sorte que tout sera, mais 39% paient au fil du temps, alors considérez cela. Un couple de réponses n'était pas inclus car il existe des défauts potentiels où ils reviendront de mauvais résultats.

3
the Tin Man

La solution exacte dépendrait du format que vous avez les nouvelles clés dans (ou si vous pouvez dériver la nouvelle clé de l'ancienne clé.)

En supposant que vous avez un hasch h dont vous souhaitez modifier les clés et un hachage new_keys qui mappe les clés actuelles des nouvelles clés que vous pouviez faire:

h.keys.each do |key|
  h[new_keys[key]] = h[key] # add entry for new key
  k.delete(key)             # remove old key
end
3
mikej

Si vous vous inquiétez de la performance, cela est plus rapide:

hsh.keys.each { |k| hsh[ key_map[k] ] = hsh.delete(k) if key_map[k] }

Vous ne créez pas de nouveau hachage et vous ne renommez que les clés nécessaires. Cela vous donne une meilleure performance.

Vous pouvez trouver plus de détails dans " Comment renommer élégamment toutes les clés d'un hachage de rubis? "

0
barbolo
h = { 'foo'=>1, 'bar'=>2 }
key_map = { 'foo'=>'foozle', 'bar'=>'barzle' }

h.each_with_object({}) { |(k,v),g| g[key_map[k]]=v }
  #=> {"foozle"=>1, "barzle"=>2}

ou

h.reduce({}) { |g,(k,v)| g.merge(key_map[k]=>v) }
  #=> {"foozle"=>1, "barzle"=>2} 
0
Cary Swoveland