rails - ruby iterate hash




Classificar hash por chave, retornar hash em Ruby (7)

Classificar hash por chave , retornar hash em Ruby

Com desestruturação e Hash # sort

hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h

Enumerável # sort_by

hash.sort_by { |k, v| k }.to_h

Hash # sort com comportamento padrão

h = { "b" => 2, "c" => 1, "a" => 3  }
h.sort         # e.g. ["a", 20] <=> ["b", 30]
hash.sort.to_h #=> { "a" => 3, "b" => 2, "c" => 1 }

Nota: <Ruby 2.1

array = [["key", "value"]] 
hash  = Hash[array]
hash #=> {"key"=>"value"}

Nota:> Ruby 2.1

[["key", "value"]].to_h #=> {"key"=>"value"}

Essa seria a melhor maneira de classificar um hash e retornar o objeto Hash (em vez de Array):

h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
# => {"a"=>1, "c"=>3, "b"=>2, "d"=>4}

Hash[h.sort]
# => {"a"=>1, "b"=>2, "c"=>3, "d"=>4}

Eu sempre usei o sort_by . Você precisa #sort_by saída #sort_by com Hash[] para fazer com que ela gere um hash, caso contrário, ela gerará uma matriz de arrays. Como alternativa, para realizar isso, você pode executar o método #to_h na matriz de tuplas para convertê-las em uma estrutura k=>v (hash).

hsh ={"a" => 1000, "b" => 10, "c" => 200000}
Hash[hsh.sort_by{|k,v| v}] #or hsh.sort_by{|k,v| v}.to_h

Há uma pergunta semelhante em " Como classificar um hash do Ruby por um valor numérico? ".


Gostei da solução no post anterior.

Eu fiz uma mini-classe, chamada class AlphabeticalHash . Ele também possui um método chamado ap , que aceita um argumento, uma ap variable Hash , como input: ap variable . Semelhante a pp ( pp variable )

Mas irá (tentar) imprimir em lista alfabética (suas chaves). Não sei se alguém mais quiser usar isso, ele está disponível como uma jóia, você pode instalá-lo como tal: gem install alphabetical_hash

Para mim, isso é bem simples. Se os outros precisarem de mais funcionalidade, avise-me, incluirei na gema.

EDIT: O crédito vai para , que me deu a idéia. :)


Não, não é (Ruby 1.9.x)

require 'benchmark'

h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
many = 100_000

Benchmark.bm do |b|
  GC.start

  b.report("hash sort") do
    many.times do
      Hash[h.sort]
    end
  end

  GC.start

  b.report("keys sort") do
    many.times do
      nh = {}
      h.keys.sort.each do |k|
        nh[k] = h[k]
      end
    end
  end
end

       user     system      total        real
hash sort  0.400000   0.000000   0.400000 (  0.405588)
keys sort  0.250000   0.010000   0.260000 (  0.260303)

Para grandes hashes, a diferença crescerá até 10x e mais


Nota: Ruby> = 1.9.2 tem um hash de preservação de pedido: as chaves de pedido são inseridas será a ordem em que são enumeradas. O abaixo se aplica a versões mais antigas ou a códigos compatíveis com versões anteriores.

Não há conceito de um hash classificado. Então não, o que você está fazendo não está certo.

Se você quiser que ele seja classificado para exibição, retorne uma string:

"{" + h.sort.map{|k,v| "#{k.inspect}=>#{v.inspect}"}.join(", ") + "}"

ou, se você quiser as chaves em ordem:

h.keys.sort

ou, se você quiser acessar os elementos em ordem:

h.sort.map do |key,value|
  # keys will arrive in order to this block, with their associated value.
end

mas, em resumo, não faz sentido falar sobre um hash classificado. Dos docs , "A ordem em que você percorre um hash por qualquer chave ou valor pode parecer arbitrária e geralmente não estará na ordem de inserção." Portanto, inserir chaves em uma ordem específica no hash não ajudará.


Você deu a melhor resposta para si mesmo no OP: Hash[h.sort] Se você deseja mais possibilidades, aqui está uma modificação no local do hash original para torná-lo classificado:

h.keys.sort.each { |k| h[k] = h.delete k }

@ordered = {}
@unordered.keys.sort.each do |key|
  @ordered[key] = @unordered[key]
end




hashmap