Estou sendo enviado um hash aninhado que precisa ser classificado por seus valores. Por exemplo:
@foo = {"a"=>{"z"=>5, "y"=>3, "x"=>88}, "b"=>{"a"=>2, "d"=>-5}}
Ao executar o seguinte:
@foo["a"].sort{|a,b| a[1]<=>b[1]}
Eu recebo:
[["y", 3], ["z", 5], ["x", 88]]
Isso é ótimo, é exatamente o que eu quero. O problema é que nem sempre vou saber quais são todas as chaves que estão sendo enviadas para mim, então preciso de algum tipo de loop. Eu tentei fazer o seguinte:
@foo.each do |e|
e.sort{|a,b| a[1]<=>b[1]}
end
Isso faz sentido para mim, pois se eu ligar manualmente para @ foo.first [0], recebo
"a"
e @ foo.first [1] retorna
{"z"=>5, "y"=>3, "x"=>8}
mas, por algum motivo, isso não está sendo organizado corretamente(por exemplo). Suponho que isso ocorra porque cada um está chamando a classificação no objeto hash inteiro, e não nos valores de "a". Como acesso os valores do hash aninhado sem saber qual é a chave?
Respostas:
6 para resposta № 1Você pode fazer um loop sobre o hash assim:
@ foo.each do | chave, valor | @foo [chave] = valor.sort {| a, b | a [1] <=> b [1]} fim
4 para resposta № 2
@foo = {"a"=>{"z"=>5, "y"=>3, "x"=>88}, "b"=>{"a"=>2, "d"=>-5}}
@bar = Hash[ @foo.map{ |key,values| [ key, values.sort_by(&:last) ] } ]
Ou, por um caminho menos complicado:
@bar = {}
@foo.each do |key,values|
@bar[key] = values.sort_by{ |key,value| value }
end
Em ambos os casos @bar
acaba por ser:
p @bar
#=> {
#=> "a"=>[["y", 3], ["z", 5], ["x", 88]],
#=> "b"=>[["d", -5], ["a", 2]]
#=> }
1 para resposta № 3
Meu colega de trabalho apresentou uma solução um pouco mais flexível que classifica recursivamente uma matriz de qualquer profundidade:
def deep_sort_by(&block)
Hash[self.map do |key, value|
[if key.respond_to? :deep_sort_by
key.deep_sort_by(&block)
else
key
end,
if value.respond_to? :deep_sort_by
value.deep_sort_by(&block)
else
value
end]
end.sort_by(&block)]
end
Você pode injetá-lo em todos os hashes e então chamar assim:
myMap.deep_sort_by { |obj| obj }
O código seria semelhante para uma matriz. Nós publicou como uma jóia para outros usarem, consulte postagem no blog para detalhes adicionais.
Disclaimer: Eu trabalho para esta empresa.
0 para a resposta № 4
no seu exemplo e
é uma matriz temporária que contém um par [chave, valor]. Nesse caso, a chave de caractere e o hash aninhado. então e.sort{|a,b|...}
tentará comparar o caractere com o hash e falhará com um erro de tempo de execução. Eu acho que você provavelmente quis digitar e[1].sort{...}
. Mas mesmo isso não funcionará corretamente, porque você não armazena o hash classificado em nenhum lugar: @foo.each
retorna o @foo original e o deixa inalterado.
A melhor solução é a sugerida por @Pan Thomakos:
@foo.each do |key, value|
@foo[key] = value.sort{ |a,b| a[1]<=>b[1] }
end