What's a clean way to sort a hash in Ruby without returning an array of key-value pair arrays?

StackOverflow https://stackoverflow.com/questions/21443612

  •  04-10-2022
  •  | 
  •  

Question

When I sort a hash in Ruby it returns an array of key-value pair arrays.

I would like it to return a hash.

What's a clean way to do this? inject?

Was it helpful?

Solution

Hashes aren't really sortable objects. Since Ruby 1.9, they maintain keys in the order in which they were added, which is convenient, but in terms of the data structure, order is not relevant.

You can test this by comparing { a: 1, b: 2 } == { b: 2, a: 1 } #=> true. The same is not true for arrays, in which the order is an important feature.

You'll find many methods in Ruby actually convert hashes to enumerables, which are closer to arrays in that they have a defined order. When returning a value from something like sort, you get an array.

You can easily convert it back into a hash using Hash[...]:

Hash[hash.sort(...)]

OTHER TIPS

You can use Hash#[]

h = {a: 1, b:0, c: 3}
arr = h.sort {|(_,v),(_, v2) | v <=> v2 }
h2 = Hash[arr] #=> {:b=>0, :a=>1, :c=>3}

Note that this is possible because hashes are enumerated based on insertion order in Ruby. This is not normally the case for hashes in other languages

As others have warned, it generally is not good practice to rely on the order of hash elements.

Assuming you want to sort on values, here's another way:

h = {a: 2, b: 1, c: 4, d: 0}

Hash[h.to_a.sort_by(&:last)]
 # => {:d=>0, :b=>1, :a=>2, :c=>4} 

If you want to have an associative array that is intrinsically sorted by its keys (instead of having to manually insert in the right order as in the other solutions proposed), you should have a look at the RBTree gem which implements a red-black tree.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top