Como troco chaves e valores em um Hash?
Eu tenho o seguinte Hash:
{:a=>:one, :b=>:two, :c=>:three}
que eu quero transformar em:
{:one=>:a, :two=>:b, :three=>:c}
Usar map
parece um pouco tedioso. Existe uma solução mais curta?
O Ruby possui um método auxiliar para o Hash que permite tratar um Hash como se estivesse invertido (em essência, permitindo acessar as chaves por meio de valores):
{a: 1, b: 2, c: 3}.key(1)
=> :a
Se você deseja manter o hash invertido, o Hash # invert deve funcionar na maioria das situações:
{a: 1, b: 2, c: 3}.invert
=> {1=>:a, 2=>:b, 3=>:c}
MAS...
Se você tiver valores duplicados, invert
descartará tudo, exceto a última ocorrência dos seus valores (porque continuará substituindo o novo valor para essa chave durante a iteração). Da mesma forma, key
retornará apenas a primeira partida:
{a: 1, b: 2, c: 2}.key(2)
=> :b
{a: 1, b: 2, c: 2}.invert
=> {1=>:a, 2=>:c}
Portanto, se seus valores forem únicos, você poderá usar Hash#invert
. Caso contrário, você pode manter todos os valores como uma matriz, assim:
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 com testes está agora no GitHub .
Ou:
class Hash
def safe_invert
self.each_with_object({}){|(k,v),o|(o[v]||=[])<<k}
end
end
each_with_object
faz mais sentido aqui do queinject
.each_with_object({}){ |i,o|k,v = *i; o[v] ||=[]; o[v] << k}
... agradávelVocê apostou que há um! Sempre há uma maneira mais curta de fazer as coisas no Ruby!
É bem simples, basta usar
Hash#invert
:Et voilà!
fonte
Isso também manipulará os valores duplicados.
fonte
Hash#inverse
da-te:enquanto o
invert
método interno está quebrado:fonte
Usando matriz
Usando Hash
fonte
Se você tiver um hash, onde as chaves são únicas, use Hash # invert :
Isso não funcionará se você tiver chaves não exclusivas, no entanto, onde apenas as últimas chaves vistas serão mantidas:
Se você tiver um hash com chaves não exclusivas, poderá fazer:
Se os valores do hash já forem matrizes, você poderá:
fonte