Cómo reemplazar una clave hash con otra clave


Tengo una condición donde, obtengo un hash

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

Y quiero este hash como

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

P. S : No se cuáles son las claves en el hash, son aleatorias que vienen con un prefijo " _ " para cada clave y no quiero guiones bajos

Author: mu is too short, 2011-06-02

8 answers

Si todas las claves son cadenas y todas ellas tienen el prefijo de subrayado, entonces puede parchear el hash en su lugar con esto:

h.keys.each { |k| h[k[1, k.length - 1]] = h[k]; h.delete(k) }

El k[1, k.length - 1] bit agarra todo k excepto el primer carácter. Si quieres una copia, entonces:

new_h = Hash[h.map { |k, v| [k[1, k.length - 1], v] }]

O

new_h = h.inject({ }) { |x, (k,v)| x[k[1, k.length - 1]] = v; x }

También puedes usar sub si no te gusta la notación k[] para extraer una subcadena:

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 }

Y, si solo algunas de las claves tienen el subrayado prefijo:

h.keys.each do |k|
    if(k[0,1] == '_')
        h[k[1, k.length - 1]] = h[k]
        h.delete(k)
    end
end

Se pueden hacer modificaciones similares a todas las otras variantes anteriores, pero estas dos:

Hash[h.map { |k, v| [k.sub(/\A_/, ''), v] }]
h.inject({ }) { |x, (k,v)| x[k.sub(/\A_/, '')] = v; x }

Debería estar bien con las claves que no tienen prefijos de subrayado sin modificaciones adicionales.

 30
Author: mu is too short,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-17 17:34:40
hash[:new_key] = hash.delete :old_key
 588
Author: gayavat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-10 14:22:50

Rails Hash tiene un método estándar para ello:

hash.transform_keys{ |key| key.to_s.upcase }

Http://api.rubyonrails.org/classes/Hash.html#method-i-transform_keys

UPD: método ruby 2.5

 111
Author: gayavat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-11 15:21:09

Puedes hacer

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

Esto debería funcionar para su caso!

 14
Author: Sadiksha Gautam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-02 05:11:39
h.inject({}) { |m, (k,v)| m[k.sub(/^_/,'')] = v; m }
 10
Author: DigitalRoss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-02 05:33:17

Si queremos cambiar el nombre de una clave específica en hash, podemos hacerlo de la siguiente manera:
Supongamos que mi hash es my_hash = {'test' => 'ruby hash demo'}
Ahora quiero reemplazar 'prueba' por 'mensaje', entonces:
my_hash['message'] = my_hash.delete('test')

 9
Author: Swapnil Chincholkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-07 11:10:58
hash.each {|k,v| hash.delete(k) && hash[k[1..-1]]=v if k[0,1] == '_'}
 2
Author: maerics,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-02 05:36:03

En las versiones de Ruby > = 2.5, puede usar Hash # transform_keys método

hash.transform_keys {|k| k.sub(/\A_/, '') }
# => { "id" => "4de7140772f8be03da000018" }
 0
Author: Santhosh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-26 06:43:36