J'ai une condition où, je reçois un hash
hash = {"_id"=>"4de7140772f8be03da000018", .....}
et je veux que ce hash
hash = {"id"=>"4de7140772f8be03da000018", ......}
P.S : Je ne sais pas quelles sont les clés du hachage, elles sont aléatoires et comportent un préfixe "_" pour chaque clé et je ne veux pas de caractères de soulignement.
Si toutes les clés sont des chaînes et qu'elles ont toutes le préfixe de soulignement, vous pouvez corriger le hachage en place avec ceci:
h.keys.each { |k| h[k[1, k.length - 1]] = h[k]; h.delete(k) }
Le k[1, k.length - 1]
bit récupère tous les k
sauf le premier caractère. Si vous voulez une copie, alors:
new_h = Hash[h.map { |k, v| [k[1, k.length - 1], v] }]
Ou
new_h = h.inject({ }) { |x, (k,v)| x[k[1, k.length - 1]] = v; x }
Vous pouvez également utiliser sub
si vous n'aimez pas la notation k[]
pour extraire une sous-chaîne:
h.keys.each { |k| h[k.sub(/\A_/, '')] = h[k]; h.delete(k) }
Hash[h.map { |k, v| [k.sub(/\A_/, ''), v] }]
h.inject({ }) { |x, (k,v)| x[k.sub(/\A_/, '')] = v; x }
Et, si seulement certaines des clés ont le préfixe de soulignement:
h.keys.each do |k|
if(k[0,1] == '_')
h[k[1, k.length - 1]] = h[k]
h.delete(k)
end
end
Des modifications similaires peuvent être apportées à toutes les autres variantes ci-dessus mais ces deux-là:
Hash[h.map { |k, v| [k.sub(/\A_/, ''), v] }]
h.inject({ }) { |x, (k,v)| x[k.sub(/\A_/, '')] = v; x }
devrait être d'accord avec les clés qui n'ont pas de préfixe de soulignement sans modifications supplémentaires.
hash[:new_key] = hash.delete :old_key
Rails Hash a une méthode standard pour cela:
hash.transform_keys{ |key| key.to_s.upcase }
http://api.rubyonrails.org/classes/Hash.html#method-i-transform_keys
UPD: méthode Ruby 2.5
tu peux faire
hash.inject({}){|option, (k,v) | option["id"] = v if k == "_id"; option}
Cela devrait fonctionner pour votre cas!
h.inject({}) { |m, (k,v)| m[k.sub(/^_/,'')] = v; m }
Si nous voulons renommer une clé spécifique dans hash, nous pouvons le faire comme suit:
Supposons que mon hash soit my_hash = {'test' => 'Ruby hash demo'}
Je souhaite maintenant remplacer "test" par "message", puis:my_hash['message'] = my_hash.delete('test')
hash.each {|k,v| hash.delete(k) && hash[k[1..-1]]=v if k[0,1] == '_'}
Je suis allé trop loin et est venu avec ce qui suit. Ma motivation derrière ceci était d'ajouter des clés de hachage pour éviter les conflits de portée lors de la fusion de hachages.
Ajoute la méthode rekey aux instances de hachage.
# Adds additional methods to Hash
class ::Hash
# Changes the keys on a hash
# Takes a block that passes the current key
# Whatever the block returns becomes the new key
# If a hash is returned for the key it will merge the current hash
# with the returned hash from the block. This allows for nested rekeying.
def rekey
self.each_with_object({}) do |(key, value), previous|
new_key = yield(key, value)
if new_key.is_a?(Hash)
previous.merge!(new_key)
else
previous[new_key] = value
end
end
end
end
my_feelings_about_icecreams = {
Vanilla: 'Delicious',
chocolate: 'Too Chocolatey',
strawberry: 'It Is Alright...'
}
my_feelings_about_icecreams.rekey { |key| "#{key}_icecream".to_sym }
# => {:Vanilla_icecream=>"Delicious", :chocolate_icecream=>"Too Chocolatey", :strawberry_icecream=>"It Is Alright..."}
{ _id: 1, ___something_: 'what?!' }.rekey do |key|
trimmed = key.to_s.tr('_', '')
trimmed.to_sym
end
# => {:id=>1, :something=>"what?!"}
Si vous passez un hachage à rekey, il fusionnera le hachage, ce qui vous permettra d'aplatir les collections. Cela nous permet d'ajouter une portée à nos clés lors de l'aplatissement d'un hachage afin d'éviter d'écraser une clé lors de la fusion.
people = {
bob: {
name: 'Bob',
toys: [
{ what: 'car', color: 'red' },
{ what: 'ball', color: 'blue' }
]
},
tom: {
name: 'Tom',
toys: [
{ what: 'house', color: 'blue; da ba dee da ba die' },
{ what: 'nerf gun', color: 'metallic' }
]
}
}
people.rekey do |person, person_info|
person_info.rekey do |key|
"#{person}_#{key}".to_sym
end
end
# =>
# {
# :bob_name=>"Bob",
# :bob_toys=>[
# {:what=>"car", :color=>"red"},
# {:what=>"ball", :color=>"blue"}
# ],
# :tom_name=>"Tom",
# :tom_toys=>[
# {:what=>"house", :color=>"blue; da ba dee da ba die"},
# {:what=>"nerf gun", :color=>"metallic"}
# ]
# }