What is a Ruby hash?
A hash is an efficient data structure that lets you store data in UNIQUE key-value pairs. It’s like a kind of dictionary that you can build & use to quickly search for something.
The “word” in this dictionary is the key, and the “definitions” are the values stored under each key.
How is this different from arrays?
Well, arrays store data in a sequential, numerical index, so the only way to retrieve a specific item is to know this index number, which by itself doesn’t have much meaning.
But hash keys can be normal words like “stock_available”, which have meaning & therefore are easier to work with.
So you’ll use arrays for LISTS of things (like a list of fruits) & hashes for a DICTIONARY of values.
Example uses include:
- A list of country names & their corresponding country codes (like ES ⇾ Spain).
- A language dictionary, where every word has a list of possible definitions.
- A list of domain name & their corresponding IP address.
One big advantage of hashes is their data retrieval speed, which is very fast if you know the key.
Make sure to take advantage of this if your data fits within a dictionary-like format.
How to Create a Hash
Ok.
I think you got a general idea of what is a hash, but how do you create one?
Like this:
{}
That’s an empty hash!
A hash with three key/value pairs looks like this:
{ a: 1, b: 2, c: 3 }
Where a
is a key, and 1
is the corresponding value for that key. Notice that the key-value pairs are separated by commas.
Now:
Let’s look at how you can use hashes in your Ruby projects with common hash methods.
Storing Hash Values
You can create a hash with a set of initial values, as we have already seen.
Here’s another example:
fruits = { coconut: 1, apple: 2, banana: 3 }
Another option is to add new values to an existing hash.
Like this:
fruits[:orange] = 4
We are asking the Ruby programming language to store the value 4
(an Integer) inside a “drawer” named :orange
(a Symbol).
NOTE: Why is there a colon before the word
:orange
when we access a value, but when we create the hash it looks likeorange:
? It’s just a syntax thing, don’t worry too much about it, but on old code you may find the hash-rocket (=>
) symbol, which is still valid but outdated.
Values inside a hash can be any kind of Ruby object.
Including:
- Strings
- Integers & Floats
- Arrays
Keys can also be anything, but symbols (like :banana
) & strings are the most common type of keys you’ll find.
Remember that…
Keys are unique, we can only have one :orange
key, or one :apple
key.
When you add the same key twice you change its value.
How to Access Values From a Hash
You access a hash by key.
If you need to access the values directly, then a hash may not be the right structure for your data.
Example:
fruits[:orange] # 4
This is the whole point of hashes, to quickly look up an item by its key.
If a key doesn’t exist, you’ll get nil
.
fruits[:peach] # nil
As an alternative, you can use the fetch
method, which allows you to provide a default value.
Example:
fruits.fetch(:peach, 0)
If you use fetch
without a default value (the 2nd argument), Ruby will raise a KeyError
exception.
That’s helpful because you’ll know what key is missing.
How to Merge Two Ruby Hashes
You can take two hashes & merge them into a new hash.
What method does this?
Well, it’s not hard to guess this one. The method’s name is merge
.
Here’s how to use it:
defaults = { a: 1, b: 2, c: 3 } preferences = { c: 4 } defaults.merge!(preferences) # {:a=>1, :b=>2, :c=>4}
Notice that because keys are unique, newer values overwrite older values.
You could use this fact for interesting solutions, like creating a “defaults” hash that users can override by passing their own hash.
If you need more control over how keys are merged you can pass a block.
Like this:
defaults.merge!(preferences) { |key, old, new| [old, new].max }
Where old
are the values coming from defaults
, and new
are the values coming from preferences
.
Multiple Values For One Key
In a dictionary…
Words are unique, but they can have multiple values (definitions) associated with them.
You can do this in Ruby!
Example:
dictionary = { opportunity: [ "a set of circumstances that makes it possible to do something", "a situation or condition favorable for attainment of a goal" ], creativity: [ "the use of imagination or original ideas to create something new", "the ability to create", "the process where new ideas emerge from combining existing ideas in new ways" ] } dictionary[:creativity][1]
Where dictionary[:creativity]
gives you an array & [1]
gives you the 2nd element from that array.
In other words:
The key is a symbol & the values are arrays. When you access the hash you get an array back which you access normally, like any other array.
How to Sort a Hash
You can sort arrays. But did you know that you can also sort hashes?
When you sort
a hash, it’s sorted by key.
Example:
{ b: 1, a: 2 }.sort # [[:a, 2], [:b, 1]]
But you can also sort them by value:
{ c: 3, b: 1, a: 2 }.sort_by(&:last)
You’ll notice that what you get from sorting a hash is not another hash…
It’s an array!
But you can convert this array back into a hash, using the to_h
method.
Get All Keys & Values From a Hash
If you want a list of all the hash keys, good news, there is a method for that!
Here it is:
{ apple: 1, banana: 2 }.keys # [:apple, :banana]
There’s also a method that gives you an array containing the values:
{ apple: 1, banana: 2 }.values # [1, 2]
If you want to know if a key exists in a hash, instead of getting an array of them, use the key?
method (btw this is an alias for include?
& has_key?
on the Hash
class).
Example:
h = { ice_cream: 1, chocolate: 2, beer: 3 } h.key?(:ice_cream) # true h.key?(:tomato) # false
As you can see, this method returns a true
or false
value, also known a a Boolean value.
Summary
You’ve learned about Ruby hashes, a helpful data structure that is composed of key-value pairs. You also learned how to access a hash by key, and how to store new data in a hash.
Now open up irb (or pry) & start playing with hashes!
Thanks for reading 🙂