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:
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 you use data that fits within a dictionary-like format.
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.
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
This is :orange
as the hash key, and 4
as its corresponding value.
Why is the colon before the word
:orange
when we access a value & after the wordorange:
when we create a hash? It’s a nicer syntax that allows you to create hashes without the hash-rocket (=>
) symbol, which is a valid, but older way to do it.
Values can be any Ruby object.
Including:
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.
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.
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
.
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.
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.
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 which 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.
This method returns a true
or false
value.
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 🙂