Let’s Hash It Out: What is a hash? And how do I Iterate through a hash?

Arrays and hashes are similar in that they are both data structures that store a collection of objects. However, they differ in the way that their objects are stored. Arrays store objects by an ordered integer index. In contrast, hashes are indexed with object key references.

Objects are encapsulated within two curly brackets and structured with key/value pairs in hashes. When you store objects in a hash, you pass in a key-value pair, which creates an associative representation of data. You can think of hashes as a dictionary. A dictionary is a collection of words with definitions. The word is the key and the definition is the value.

Each individual key points to a value, which in turn is related back to the key. Keys can be objects of any data type (strings, integers, symbols, expressions, etc.) but they must be unique. Keys can’t be duplicated or else it will be overwritten with the latest key assignment. Values are more flexible. Hash values can be objects of any type and also be duplicated.

The key is on the left hand side of the hash rocket

and the hash rocket is the assignee that points to the key’s value, which is on the right side.

To put into prospective how a hash looks like:

hash syntax: my_hash = {key1 => value1, key2 => value2, key3 => value3}


alternative hash syntaxes:

You can also use symbols for the keys of a hash or instead of the rocket hash, key-value pairs can be written as:

To create a new hash, you can initialize or create a new hash by either using a constructor notation:

*Hash must be capitalized for Hash.new because it is a new instance of a hash

OR by a literal notation:

Hashes have an advantage over arrays in that they can use any object as an index since it is not an ordered collection of objects.

You can access a value in a hash with its key:

hash[key] => value


hash[:key] => value

Be careful, as hashes have a default value of nil. If you attempt to return a value that is associated with a non-existing key within the hash, the return value will be nil.

A new empty hash has no collection of objects. You can then proceed to add objects to your new empty hash.

To add a new key-value pair to a hash:

hash[new_key] = “new value”

How to iterate through hashes:

Since hash keys are not ordered, objects are iterated in the order in which they were added to the hash and by key-value pairs. To iterate over hashes, you have to break the collection down into objects (key-value pairs).

The .each/.each_pair method:

The .each method can be used on arrays and hashes. However, the .each_pair method specifically targets the key-value pair. Both methods can be used interchangeably for hashes.

The .each and .each_pair takes in two arguments for the key and value pair. Then it performs a block of code on each and every key-value pair at a time within that hash. The first argument refers to the key and the second to the value. The output will be the same for both methods.

Remember that the .each method returns the original collection on which you are calling the method.

You should name your arguments so that your code is easier to read. A trick to naming your arguments if you don’t know what to name them is to simply use |key, value| first to see what the information returns for the key and value. Once you see what the key and value returns, you can then rename the key and value meaningful names within the pipelines.

The .each_key method:

The .each_key method is used to iterate over the keys of a hash and returns only the keys of the hash.

The .each_value method:

The .each_value method is used to iterate over the values of a hash and returns only the values of the hash.

Other useful enumerable iteration methods:

  • .delete: deletes the key-value pair and returns the value of whose key matches up with the key in the argument parameters
  • .delete_if: deletes every key-value pair for which the block evaluates to true.
  • .fetch: select returns the original objects where the code block you gave it returned true
  • merge(other_hash){|key, oldval, newval| block}: returns a new hash with the merged information of the other_hash combined with the contents of the current hash
  • merge!(other_hash){|key, oldval, newval| block}: similiar to merge but the ! (bang!) operates on the original hash itself and returns a modified hash with the merged information of the other_hash with the contents of the current hash
  • .pretty_print(obj): returns the first key-value pair that matches the object passed in
  • .reject {| key, value | block }: same as .delete_if but instead returns a copy of the hash
  • select {|key, value| block}: returns a new hash with the objects that returned true

Okay, so now that you’re familiar with hashes, know how they work, some of the syntaxes and usage…let’s move onto nested hashes. Nested hashes are a bit tricker because they’re multi-dimensional. It’s easy to feel like you’re falling into rabbit hole when you’re working with nested hashes.

Don’t worry or get intimidated! We can hold hands and go through this together.

Like what you read? Give Jenny Lai a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.