/ / Classificando hash de hashes por valor (e retorna o hash, não uma matriz) - ruby, estruturas de dados, hash, classificação

Classificando Hash of Hashes por valor (e retorna o hash, não um array) - ruby, estruturas de dados, hash, classificação

Eu tenho o seguinte hash:

user = {
"user" => {
"title" => {"weight" => 1, .... }
"body" => {"weight" => 4, ....}
....
....
}
}

É possível obter o usuário classificado pela chave de peso de seus hashes filho?

Eu olhei no Hash.sort, mas parece que ele retorna array ao invés do meu hash original ordenado.

Respostas:

11 para resposta № 1

Em Ruby 1.9, Hashes são classificados, mas Hash#sort ainda retorna um Array do Arrays. Imagine isso! Isso implica que você pode construir seu próprio método de classificação sobre ele.

class Hash
def sorted_hash(&block)
self.class[sort(&block)]   # Hash[ [[key1, value1], [key2, value2]] ]
end
end

Hashes são não classificados em Ruby 1.8. Se você quiser compatibilidade Ruby 1.8, você pode usar o ActiveSupport OrderedHash. Ele se comporta como um 1.9-Hash, então você pode definir o mesmo sorted_hash método sobre ele:

class ActiveSupport::OrderedHash
def sorted_hash(&block)
self.class[sort(&block)]
end
end

hash = ActiveSupport::OrderedHash.new
hash["b"] = "b"
hash["a"] = "a"
hash               #=> {"b"=>"b", "a"=>"a"}  => unsorted
hash.sorted_hash   #=> {"a"=>"a", "b"=>"b"}  => sorted!

Você tem que copiar o sorted_hash método para o seu código, porque não existe por padrão!

Atualização para classificação profunda: Se você estiver procurando classificar algo diferente da chave hash, passe um bloco para o sorted_hash método como segue (assumindo a implementação de cima):

hash = ActiveSupport::OrderedHash.new
hash["a"] = { "attr" => "2", "..." => "..." }
hash["b"] = { "attr" => "1", "..." => "..." }

# Unsorted.
hash
#=> {"a"=>{"attr"=>"2", "..."=>"..."}, "b"=>{"attr"=>"1", "..."=>"..."}}

# Sort on the "attr" key. (Assuming every value is a Hash itself!)
hash.sorted_hash { |a, b| a[1]["attr"] <=> b[1]["attr"] }
#=> {"b"=>{"attr"=>"1", "..."=>"..."}, "a"=>{"attr"=>"2", "..."=>"..."}}

8 para resposta № 2

Hashes são estruturas de dados fundamentalmente não-selecionadas; Hash#sort é, de fato, o que você quer. Ou isso, ou classificar uma lista de chaves e, em seguida, usar isso para enumerar quando é hora de produzir o hash, em vez de enumerar diretamente sobre o hash usando seus próprios métodos.