Como classificar um Ruby Hash pelo valor numérico?


154

Eu tenho um contador de hash que estou tentando classificar por contagem. O problema que eu estou enfrentando é que a função Hash.sort padrão classifica números como seqüências de caracteres e não por tamanho de número.

ie Hash dado:

metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 }

Executando este código:

metrics.sort {|a1,a2| a2[1]<=>a1[1]}

retornará uma matriz classificada:

[ 'siteb.com', 9, 'sitea.com', 745, 'sitec.com', 10]

Embora 745 seja um número maior que 9, 9 será exibido primeiro na lista. Ao tentar mostrar quem tem a maior contagem, isso está dificultando minha vida. :)

Alguma idéia de como classificar um hash (ou mesmo um array) pelo tamanho do valor numérico?

Agradeço qualquer ajuda.


qual versão ruby ​​você usa? o resultado espécie é muito estranho
fl00r

Respostas:


268

Não faço ideia de como você obteve seus resultados, pois ele não classificaria por valor da string ... Você deve reverter a1e a2no seu exemplo

A melhor maneira, em qualquer caso (conforme Mladen), é:

metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 }
metrics.sort_by {|_key, value| value}
  # ==> [["siteb.com", 9], ["sitec.com", 10], ["sitea.com", 745]]

Se você precisar de um hash como resultado, poderá usar to_h(no Ruby 2.0+)

metrics.sort_by {|_key, value| value}.to_h
  # ==> {"siteb.com" => 9, "sitec.com" => 10, "sitea.com", 745}

84
ou simplesmentesort_by{|k,v| v}
Mladen Jablanović

Meu número estava retornando como uma string, que o corrigia. Eu tinha a2 e a1 nessa ordem, porque queria que os resultados classificassem como decentes.
Dustin M.

é por isso que eu amo Ruby ... esse problema é dor de cabeça em outras línguas. Tão simples
Hady Elsahar 31/12/12

18
@Elchin: você pode usarmetrics.sort_by{ |k, v| v }.reverse.to_h
Marc-André Lafortune

4
Na verdade, é ainda mais simples como: hash.sort_by (&: last) com a mesma ressalva em obter uma matriz de pares vs. um Hash.
Gerry Gleason


14

Já respondeu mas ainda. Mude seu código para:

metrics.sort {|a1,a2| a2[1].to_i <=> a1[1].to_i }

Convertido em strings ao longo do caminho ou não, isso fará o trabalho.


9

Não é esse o comportamento que estou vendo:

irb(main):001:0> metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" =>
 10 }
=> {"siteb.com"=>9, "sitec.com"=>10, "sitea.com"=>745}
irb(main):002:0> metrics.sort {|a1,a2| a2[1]<=>a1[1]}
=> [["sitea.com", 745], ["sitec.com", 10], ["siteb.com", 9]]

É possível que, em algum ponto da linha, seus números estejam sendo convertidos em strings? Há mais código que você não está postando?


Ahh, seu direito, parece que o resultado no meu código estava retornando como uma string. Tipos de dados traquinas. :) Às vezes, estou muito perto do problema. Obrigado.
Dustin M.

1
Sim. Ocasionalmente, ouço alguém se referir a Ruby como "não digitado". Oh, não, é definitivamente digitado. Não é apenas estaticamente digitado. :)
Jacob Mattison
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.