array - Ordena hash por clave, vuelve hash en Ruby
hash.map ruby (10)
Ordena hash por clave , vuelve hash en Ruby
Con desestructuración y Hash # sort.
hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h
Enumerable # sort_by
hash.sort_by { |k, v| k }.to_h
Hash # ordenar con comportamiento predeterminado
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"}
¿Sería esta la mejor manera de ordenar un hash y devolver un objeto Hash (en lugar 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}
En Ruby 2.1 es simple:
h.sort.to_h
Me gustó la solución en el post anterior.
Hice una mini-clase, la llamé class AlphabeticalHash
. También tiene un método llamado ap
, que acepta un argumento, un Hash
, como entrada: ap variable
. Similar a pp ( pp variable
)
Pero (intentará) imprimirá en la lista alfabética (sus claves). No sé si alguien más quiere usar esto, está disponible como una gema, puede instalarlo como tal: gem install alphabetical_hash
Para mí, esto es lo suficientemente simple. Si otros necesitan más funcionalidad, hágamelo saber, lo incluiré en la gema.
EDITAR: Crédito es para , quien me dio la idea. :)
No, no lo es (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 la diferencia crecerá hasta 10x y más.
Nota: Ruby> = 1.9.2 tiene un hash de conservación de orden: las claves de orden que se insertan serán el orden en que se enumeran. Lo siguiente se aplica a versiones anteriores o a código compatible con versiones anteriores.
No hay concepto de un hash ordenado. Así que no, lo que estás haciendo no está bien.
Si desea que esté ordenado para su visualización, devuelva una cadena:
"{" + h.sort.map{|k,v| "#{k.inspect}=>#{v.inspect}"}.join(", ") + "}"
O, si quieres las llaves en orden:
h.keys.sort
O, si quieres acceder a los elementos en orden:
h.sort.map do |key,value|
# keys will arrive in order to this block, with their associated value.
end
pero en resumen, no tiene sentido hablar de un hash ordenado. De los docs , "El orden en el que atraviesa un hash por clave o valor puede parecer arbitrario, y generalmente no estará en el orden de inserción". Así que insertar claves en un orden específico en el hash no ayudará.
Siempre he usado sort_by
. #sort_by
envolver la salida #sort_by
con Hash[]
para hacer que #sort_by
un hash, de lo contrario, genera una matriz de matrices. Alternativamente, para lograr esto, puede ejecutar el método #to_h
en la matriz de tuplas para convertirlas en una estructura 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
Hay una pregunta similar en " ¿Cómo ordenar un Ruby Hash por valor numérico? ".
Te diste la mejor respuesta en el OP: Hash[h.sort]
Si deseas más posibilidades, aquí está la modificación en el lugar del hash original para que sea ordenado:
h.keys.sort.each { |k| h[k] = h.delete k }
Tuve el mismo problema (tuve que ordenar mis equipos por su nombre) y lo resolví así:
<% @equipments.sort.each do |name, quantity| %>
...
<% end %>
@equipments es un hash que compilo en mi modelo y devuelvo en mi controlador. Si llama a .sort, ordenará el hash en función de su valor clave.
ActiveSupport::OrderedHash es otra opción si no desea usar ruby 1.9.2 o hacer rodar sus propias soluciones.
@ordered = {}
@unordered.keys.sort.each do |key|
@ordered[key] = @unordered[key]
end