Here’s a quick and easy way to sort a Ruby hash by its keys. The ability to sort recursively and provide a custom sort block are also available features.
The Method
I took the approach of monkey patching a sort_by_key method into the Ruby Hash class itself. The method can be easily modified and placed into class If you’d prefer to take more procedural approach.
1 2 3 4 5 6 7 8 9 10 11 | class Hash def sort_by_key(recursive=false, &block) self.keys.sort(&block).reduce({}) do |seed, key| seed[key] = self[key] if recursive && seed[key].is_a?(Hash) seed[key] = seed[key].sort_by_key(true, &block) end seed end end end |
Basic Usage
Below is a very disorganized nested hash and an example of using the recursive sort option to get it back into line using Hash.sort_by_key(true).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | h = { "b" => 2, "c" => 3, "a" => 1, "d" => { "b" => 2, "c" => 3, "a" => 1, "d" => { "b" => 2, "c" => 3, "a" => 1 } } } h.sort_by_key(true) # => { "a" => 1, "b" => 2, "c" => 3, "d" => { "a" => 1, "b" => 2, "c" => 3, "d" => { "a" => 1, "b" => 2, "c" => 3 } } } |
What About Mixed Type Hash Keys!?
If we continued the example from above by executing h[:a] = “one”, and then calling h.sort_by_key, we would be slapped in the face with an exception of …
ArgumentError: comparison of String with :a failed
Looking at the backtrace it appears the call to self.keys.sort is the culprit.
So What’s The Solution?
There are a couple of solutions depending on your coding style and opinion on ruby convention.
- April 30, 2012
- Categories: Development
