¿Cómo cambio claves y valores en un hash?
Tengo el siguiente Hash:
{:a=>:one, :b=>:two, :c=>:three}
que quiero transformar en:
{:one=>:a, :two=>:b, :three=>:c}
Usar map
parece bastante tedioso. ¿Hay una solución más corta?
Ruby tiene un método auxiliar para Hash que le permite tratar un Hash como si estuviera invertido (en esencia, al permitirle acceder a las claves mediante valores):
{a: 1, b: 2, c: 3}.key(1)
=> :a
Si desea mantener el hash invertido, Hash # invert debería funcionar para la mayoría de las situaciones:
{a: 1, b: 2, c: 3}.invert
=> {1=>:a, 2=>:b, 3=>:c}
PERO...
Si tiene valores duplicados, invert
descartará todos, excepto la última aparición de sus valores (porque seguirá reemplazando el nuevo valor para esa clave durante la iteración). Del mismo modo, key
solo devolverá el primer partido:
{a: 1, b: 2, c: 2}.key(2)
=> :b
{a: 1, b: 2, c: 2}.invert
=> {1=>:a, 2=>:c}
Entonces, si sus valores son únicos, puede usarlos Hash#invert
. De lo contrario, puede mantener todos los valores como una matriz, como este:
class Hash
# like invert but not lossy
# {"one"=>1,"two"=>2, "1"=>1, "2"=>2}.inverse => {1=>["one", "1"], 2=>["two", "2"]}
def safe_invert
each_with_object({}) do |(key,value),out|
out[value] ||= []
out[value] << key
end
end
end
Nota: Este código con pruebas ahora está en GitHub .
O:
class Hash
def safe_invert
self.each_with_object({}){|(k,v),o|(o[v]||=[])<<k}
end
end
each_with_object
tiene más sentido aquí queinject
.each_with_object({}){ |i,o|k,v = *i; o[v] ||=[]; o[v] << k}
... agradable¡Apuesto a que hay uno! ¡Siempre hay una forma más corta de hacer las cosas en Ruby!
Es bastante simple, solo usa
Hash#invert
:Et voilà!
fuente
Esto también manejará los valores duplicados.
fuente
Hash#inverse
te dio:mientras que el
invert
método incorporado está roto:fuente
Usando Array
Usando Hash
fuente
Si tiene un hash donde las claves son únicas, puede usar Hash # invert :
Sin embargo, eso no funcionará si tiene claves no únicas, donde solo se guardarán las últimas claves vistas:
Si tiene un hash con claves no únicas, puede hacer:
Si los valores del hash ya son matrices, puede hacer:
fuente