Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort a Ruby Hash alphabetically by keys

Tags:

sorting

ruby

I am trying to sort a Hash alphabetically by key, but I can't seem to find a way to do it without creating my own Sorting class. I found the code below to sort by value if it's an integer and I am trying to modify it but not having any luck.

temp["ninjas"]=36 temp["pirates"]=12 temp["cheese"]=222 temp.sort_by { |key, val| key } 

My goal is to order the Hash by key then output the values. I will have to do this multiple times with different hash orders but the same values.

like image 397
Rilcon42 Avatar asked Dec 09 '14 17:12

Rilcon42


People also ask

How do I sort a hash key in Ruby?

If you want to access a Hash in a sorted manner by key, you need to use an Array as an indexing mechanism as is shown above. This works by using the Emmuerator#sort_by method that is mixed into the Array of keys. #sort_by looks at the value my_hash[key] returns to determine the sorting order.

Can you sort a hash Ruby?

Sorting Hashes in RubyTo sort a hash in Ruby without using custom algorithms, we will use two sorting methods: the sort and sort_by. Using the built-in methods, we can sort the values in a hash by various parameters.

Do Ruby Hashes preserve order?

As of Ruby 1.9, hashes also maintain order, but usually ordered items are stored in an array.

How do you check if a hash has a key Ruby?

Overview. We can check if a particular hash contains a particular key by using the method has_key?(key) . It returns true or false depending on whether the key exists in the hash or not.


2 Answers

Assuming you want the output to be a hash which will iterate through keys in sorted order, then you are nearly there. Hash#sort_by returns an Array of Arrays, and the inner arrays are all two elements.

Ruby's Hash has a constructor that can consume this output.

Try this:

temp = Hash[ temp.sort_by { |key, val| key } ] 

or more concisely

temp = temp.sort_by { |key| key }.to_h 

If your hash has mixed key types, this will not work (Ruby will not automatically sort between Strings and Symbols for instance) and you will get an error message like comparison of Symbol with String failed (ArgumentError). If so, you could alter the above to

temp = Hash[ temp.sort_by { |key, val| key.to_s } ]  

to work around the issue. However be warned that the keys will still retain their original types which could cause problems with assumptions in later code. Also, most built-in classes support a .to_s method, so you may get unwanted results from that (such as unexpected sort order for numeric keys, or other unexpected types).

You could, in addition, convert the keys to Strings with something like this:

temp = Hash[ temp.map { |key, val| [key.to_s, val] }.sort ]  

. . . although this approach would lose information about the type of the original key making it impossible to refer back to the original data reliably.

like image 195
Neil Slater Avatar answered Sep 19 '22 22:09

Neil Slater


sorted_by_key = Hash[original_hash.sort] 

will create a new Hash by inserting the key/values of original_hash alphabetically by key. Ruby 2.x hashes remember their insertion order, so this new hash will appear sorted by key if you enumerate it or output it.

If you insert more elements in a non-alphabetical order, this won't hold of course.

Also, this assumes the original hash keys are all sortable/comparable.

like image 35
Trashpanda Avatar answered Sep 16 '22 22:09

Trashpanda