Comment remplacer une clé de hachage par une autre clé

J'ai une condition où, je reçois un hachage

  hash = {"_id"=>"4de7140772f8be03da000018", .....}

Et je veux ce hachage comme

  hash = {"id"=>"4de7140772f8be03da000018", ......}

P. S : Je ne sais pas quelles sont les clés dans le hachage, elles sont aléatoires qui vient avec un préfixe " _ " pour chaque clé et je ne veux pas de soulignement

152
demandé sur mu is too short 2011-06-02 08:54:49

8 réponses

Si toutes les clés sont des chaînes et toutes ont le préfixe de soulignement, alors vous pouvez patcher 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] peu de s'approprier la totalité de 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 k[] notation pour l'extraction d'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 trait de soulignement préfixe:

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 faites à toutes les autres variantes ci-dessus, mais ces deux:

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éfixes de soulignement sans modifications supplémentaires.

30
répondu mu is too short 2013-09-17 17:34:40
hash[:new_key] = hash.delete :old_key
588
répondu gayavat 2013-10-10 14:22:50

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: Ruby 2.5 méthode

111
répondu gayavat 2018-01-11 15:21:09

Vous pouvez faire

hash.inject({}){|option, (k,v) | option["id"] = v if k == "_id"; option}

Cela devrait fonctionner pour votre cas!

14
répondu Sadiksha Gautam 2011-06-02 05:11:39
h.inject({}) { |m, (k,v)| m[k.sub(/^_/,'')] = v; m }
10
répondu DigitalRoss 2011-06-02 05:33:17

Si nous voulons renommer la clé de hachage alors nous pouvons le faire comme suit:
supposons que mon hachage soit my_hash = {'test' => 'ruby hash demo'}
Maintenant, je veux remplacer "test" par "message", puis:
my_hash['message'] = my_hash.delete('test')

9
répondu Swapnil Chincholkar 2013-11-07 11:10:58
hash.each {|k,v| hash.delete(k) && hash[k[1..-1]]=v if k[0,1] == '_'}
2
répondu maerics 2011-06-02 05:36:03

Dans les versions Ruby > = 2.5, vous pouvez utiliser Hash # transform_keys Méthode

hash.transform_keys {|k| k.sub(/\A_/, '') }
# => { "id" => "4de7140772f8be03da000018" }
0
répondu Santhosh 2018-09-26 06:43:36