2010-10-28 35 views

Respuesta

1

Asumo que desea cambiar el hash keys sin cambiar los valores:

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 

resultado: { "nr" => "123", " nombre "=>" Herrmann Hofreiter "," hourse "=>" 010 000 777 "," tierra "=>" tierra alta "}

+0

Un momento de autopromoción ☺️, pero solo para dejarlo aquí: si necesitas algo un poco más complejo (como seleccionar teclas particulares al mismo tiempo o forzar tipos de valores, etc.), armé una pequeña lib: https : //github.com/smileart/hash_remapper – smileart

3

La solución exacta dependerá del formato que tiene las nuevas llaves en (o si se puede derivar la nueva clave de la clave de edad.)

Asumiendo que tiene un hash h cuyas claves que desea modificar y un hash que mapea new_keys las claves actuales a las nuevas claves que podía hacer:

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

Esto eliminará un valor para' clave' cuando ' new_keys' accidentalmente devuelve 'clave' en sí misma para alguna' clave'. La respuesta de Barbolos a esta pregunta: http://stackoverflow.com/questions/4137824 supera este problema. – sawa

+2

en lugar de esto, puede usar 'h.keys.each {| key | h [new_keys [key]] = h.delete (key)} ' – Selvamani

+0

@Selvamani, mira mi respuesta y crea una respuesta a partir de tu comentario. –

73

Asumiendo que tiene un Hash que mapea claves antiguas a las nuevas llaves, se podría hacer algo como

hsh.map {|k, v| [key_map[k], v] }.to_h 
+4

¡Eres el hombre! ¡Tu hash es totalmente increíble! Gracias de nuevo por esta joya!:) – CalebHC

+1

También asume que 'key_map' se define como un hash de pares clave/valor donde la clave es la clave anterior y el valor es la nueva clave que se intercambia. –

-1

Si también se preocupan por el rendimiento, esto es más rápido:

hsh.keys.each { |k| hsh[ key_map[k] ] = hsh.delete(k) if key_map[k] } 

No se crea un nuevo hash y sólo cambia el nombre de las claves necesarias. Eso te da un mejor rendimiento.

Usted puede encontrar más detalles en "How to elegantly rename all keys in a hash in Ruby?"

+0

Esto se rompe si' key_map [k] 'es nil . –

3

Otra manera de hacerlo es:

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} 

Descomponiéndola:

new_keys 
.values # => ["foozle", "barzle"] 
.zip(
    hash.values_at(*new_keys.keys) # => [1, 2] 
) # => [["foozle", 1], ["barzle", 2]] 
.to_h 
# => {"foozle"=>1, "barzle"=>2} 

Es hora de referencia ..

Aunque me gusta la simplicidad de la respuesta de Jörn, estoy no era seguro que era tan rápido como debería ser, entonces vi el comentario 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% 

Estos están funcionando muy cerca de la velocidad junto sabia, por lo que cualquier servirá, pero el 39% paga con el tiempo, así que tenlo en cuenta. Un par de respuestas no fueron incluidas porque hay fallas potenciales en las que devolverían malos resultados.

0
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} 

o

h.reduce({}) { |g,(k,v)| g.merge(key_map[k]=>v) } 
    #=> {"foozle"=>1, "barzle"=>2} 
+0

Creo que llamar fusión para cada clave será comparativamente lento – Josh

+0

@Josh, estás en lo cierto. Volví a ejecutar el benchmark de @TinMan con mis dos métodos agregados y obtuve los siguientes resultados: "selvamani es más rápido que ttm en 19.99% ± 1.0%; ttm es similar a caryewo (usa' each_with_object'); caryewo es similar a mittag; mittag es más rápido que el caryred (usa 'reduce') en un 70.0% ± 10.0%". –

Cuestiones relacionadas