ruby - tabla - Cómo cambiar todas las claves de un hash por un nuevo conjunto de claves dadas
tabla hash implementacion (6)
La solución exacta dependerá del formato en el que tenga las claves nuevas (o si puede derivar la nueva clave de la clave anterior).
Suponiendo que tiene un hash h
cuyas claves desea modificar y un hash new_keys
que mapea las claves actuales con las nuevas claves que podrí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
¿Cómo cambio todas las claves de un hash por un nuevo conjunto de claves?
¿Hay alguna manera de hacerlo elegantemente?
Otra forma 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}
Rompiéndolo:
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, no estaba seguro de que fuera tan rápido como debería, 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 se ejecutan muy cerca de la velocidad, por lo que cualquiera lo hará, pero el 39% vale la pena con el tiempo, así que ten en cuenta. Un par de respuestas no fueron incluidas porque hay fallas potenciales en las que devolverían malos resultados.
Si también te preocupa el rendimiento, es más rápido:
hsh.keys.each { |k| hsh[ key_map[k] ] = hsh.delete(k) if key_map[k] }
No crea un nuevo Hash y cambia el nombre solo de las claves necesarias. Eso te da un mejor rendimiento.
Puede encontrar más detalles en " ¿Cómo renombrar elegantemente todas las teclas en un hash en Ruby? "
Suponiendo que tiene un Hash
que asigna claves antiguas a claves nuevas, podría hacer algo como
hsh.map {|k, v| [key_map[k], v] }.to_h
supongo que quiere cambiar las keys
hash sin cambiar los valores:
hash = {
"nr"=>"123",
"name"=>"Herrmann Hofreiter",
"pferd"=>"010 000 777",
"land"=>"hight land"
}
header = ["aa", "bb", "cc", "dd"]
new_hash = header.zip(hash.values).to_h
Resultado:
{
"aa"=>"123",
"bb"=>"Herrmann Hofreiter",
"cc"=>"010 000 777",
"dd"=>"high land"
}
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}