49 votes

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

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

Existe-t-il un moyen de le faire de manière élégante ?

79voto

Jörg W Mittag Points 153275

En supposant que vous disposiez d'un Hash qui fait correspondre les anciennes clés aux nouvelles, vous pourriez faire quelque chose comme

hsh.transform_keys(&key_map.method(:[]))

4 votes

Vous êtes l'homme de la situation ! Votre hachage est tout à fait génial ! Merci encore pour ce bijou ! :)

1 votes

Il suppose également que vous avez key_map défini comme un hachage de paires clé/valeur où la clé est l'ancienne clé et la valeur est la nouvelle clé qui est échangée.

0 votes

Quelqu'un pourrait expliquer comment le &key_map.method(:[]) fonctionne ?

18voto

Santosh Points 6791

Ruby 2.5 a Hash#transform_keys ! méthode. Exemple d'utilisation d'une carte de 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 raccourci symbol#toproc avec transform_keys Eg :

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

4voto

Kiry Meas Points 407

Je suppose que vous souhaitez modifier le hachage 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"
}

3voto

the Tin Man Points 69148

Une autre façon de procéder est la suivante :

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}

La décomposition :

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 l'heure du bilan...

Bien que j'apprécie la simplicité de la réponse de Jörn, je n'étais pas sûr qu'elle soit aussi rapide qu'elle devrait l'ê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%

Les vitesses sont très proches les unes des autres, donc n'importe laquelle fera l'affaire, mais 39% est rentable sur le long terme, alors tenez-en compte. Quelques réponses n'ont pas été incluses parce qu'il y a des failles potentielles où elles donneraient de mauvais résultats.

2voto

mikej Points 30224

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

En supposant que vous disposiez d'un hachage h dont vous souhaitez modifier les clés et un hash new_keys qui associe les clés actuelles aux nouvelles clés que vous pourriez utiliser :

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

1 votes

Cela supprimera une valeur pour key quand new_keys se retrouve accidentellement à renvoyer key pour un certain nombre de key . la réponse de barbolos à cette question : stackoverflow.com/questions/4137824 permet de surmonter ce problème.

3 votes

Au lieu de cela, vous pouvez utiliser h.keys.each { |key| h[new_keys[key]] = h.delete(key)}

0 votes

@Selvamani, voir ma réponse, et créer une réponse à partir de votre commentaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X