Comment changer toutes les clés d'un hachage par un nouvel ensemble de clés donné?Comment changer toutes les clés d'un hachage par un nouvel ensemble de clés données
Existe-t-il un moyen de le faire avec élégance?
Comment changer toutes les clés d'un hachage par un nouvel ensemble de clés donné?Comment changer toutes les clés d'un hachage par un nouvel ensemble de clés données
Existe-t-il un moyen de le faire avec élégance?
Je suppose que vous voulez changer le hachage keys
sans changer les valeurs:
hash = {"nr"=>"123", "name"=>"Herrmann Hofreiter", "pferd"=>"010 000 777", "land"=>"hight land"}
header = ["nr", "name", "hourse", "land"]
new_hash = header.zip(hash.values).to_h
résultat: { "nr" => "123", " name "=>" Herrmann Hofreiter "," hourse "=>" 010 000 777 "," land "=>" haute terre "}
La solution exacte dépendra du format que vous avez les nouvelles clés (ou si vous pouvez déduire la nouvelle clé de l'ancienne clé.)
En supposant que vous avez un hachage h
dont les clés que vous souhaitez modifier et un hachage new_keys
qui mappe les clés actuelles aux nouvelles clés que vous pourriez faire:
h.keys.each do |key|
h[new_keys[key]] = h[key] # add entry for new key
k.delete(key) # remove old key
end
Ceci supprimera une valeur pour' key' quand ' new_keys' arrive accidentellement à retourner 'key' lui-même pour quelque' key'. La réponse de barbolos à cette question: http://stackoverflow.com/questions/4137824 surmonte ce problème. – sawa
au lieu de cela, vous pouvez utiliser 'h.keys.each {| key | h [new_keys [clé]] = h.delete (touche)} ' – Selvamani
@Selvamani, voir ma réponse, et créer une réponse à partir de votre commentaire. –
en supposant que vous avez une Hash
qui associe les anciennes clés de nouvelles clés, vous pouvez faire quelque chose comme
hsh.map {|k, v| [key_map[k], v] }.to_h
Vous êtes l'homme! Votre hash est totalement génial! Merci encore pour ce petit bijou!:) – CalebHC
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é permutée. –
Si vous vous inquiétez également sur la performance, c'est plus rapide:
hsh.keys.each { |k| hsh[ key_map[k] ] = hsh.delete(k) if key_map[k] }
Vous ne créez pas une nouvelle Hash et vous renommer uniquement les clés nécessaires. Cela vous donne de meilleures performances.
Vous pouvez trouver plus de détails dans "How to elegantly rename all keys in a hash in Ruby?"
Cela casse si' key_map [k] 'est nul . –
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}
Décomposant:
new_keys
.values # => ["foozle", "barzle"]
.zip(
hash.values_at(*new_keys.keys) # => [1, 2]
) # => [["foozle", 1], ["barzle", 2]]
.to_h
# => {"foozle"=>1, "barzle"=>2}
Il est temps de référence ..
Bien que j'aime la simplicité de la réponse de Jörn, je n'étais pas sûr qu'il était aussi vite qu'il devrait être, 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%
Ceux-ci sont en cours d'exécution très proche vitesse ensemble sage, de sorte que toute fera, mais 39% rapporte au fil du temps alors considérez cela. Quelques réponses n'ont pas été incluses parce qu'il y a des failles potentielles dans lesquelles elles renverraient de mauvais résultats.
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}
Je pense que l'appel à la fusion pour chaque touche sera relativement lent – Josh
@Josh, vous avez raison. J'ai re-couru le benchmark de theTinMan avec mes deux méthodes ajoutées et obtenu les résultats suivants: "selvamani est plus rapide que ttm de 19.99% ± 1.0%, ttm est similaire à caryewo (utilise' each_with_object'), caryewo est similaire à mittag; est plus rapide que caryred (utilise 'réduire') de 70,0% ± 10,0%". –
Un moment de promotion personnelle but, mais juste pour le laisser ici: si quelque chose d'un peu plus complexe est nécessaire (comme sélectionner des touches particulières en même temps ou contraindre des types de valeurs et ainsi de suite), je mets une minuscule lib: https : //github.com/smileart/hash_remapper – smileart