Hashes in Ruby
Tags: ruby, codenewbie, beginners, tutorial
Published: 2020-11-22 23:43:19

# Welcome
Good day, dear friends, coders, and enthusiasts! Let’s walk through one more thing in our beloved Ruby PL. Come and learn something new and add up to our knowledge base. This time it will be Hashes and how we use them in Ruby.  
  
# What is a Hash?
The same as Arrays, Hashes are a set of elements with certain features. At a first sight, Hashes kind of resemble Arrays in some aspect. As you know, elements in Arrays each have an ordering number, i.e. index. On the other side, Hash elements have keys, that are unique for each of the Hash elements. So, each element in Hash is a pair of key and its value. Let’s take a look at the example:
* Names of countries and their shortcodes (TKM=>Turkmenistan, ESP=>Spain, NZ =>New Zealand and etc.)
* Word and its translation in a dictionary (cat => кошка, dog => собака and etc.)
* Domain address and its IP (www.medium.com => 192.159.043.129 and etc.)
  
As you see in the example above, each pair is accepted as an element in Hash. If we accept the element index as part of the element in Arrays, they can now resemble Hash elements.  
According to the example above:
* **NZ** — is a key / **New Zealand** — is a value
* **cat** — is a key / **кошка** — is a value
* **www.medium.com** — is a key / **192.159.043.129** — is a value.
and etc.  
 
It means that, when we refer to the ‘cat’ key, we can get its value ‘кошка’. When referring to the key ‘NZ’ key, we can get its value ‘New Zealand’. We can conclude that the ordering in Hashes is not important. The important part is that the elements have unique keys and when that we can access element (pair) values by referring to the keys.  
  
One more thing to note is that each key in a Hash must be unique. When we refer to the ‘NZ’ key, it must return its ‘New Zealand’ value.  
 
But values can in different elements can be the same. Values do not have to be unique. For instance:  

{NZ => ‘New Zealand’, NZE => ‘New Zealand’, ES => ‘Spain’, ESP => ‘Spain’, NZL => ‘New Zealand’, SPN => ‘Spain’}  
  
What’s important is that each key must be unique, so that the Hash knows which pair we refer to when we provide a key to its element. But values can be the same in many of its elements.
  
# Creating a new Hash element
  
Hashes also have special brackets. We use curly brackets to define a Hash. We also use colons to separate key and value pairs.  

```
# An empty hash 
{}

# Smartphones and developer companies
phones = {Mi_Note_9: 'Xiao Mi', Galaxy_A5: "Samsung", Iphone_10: 'Apple', Diamond_S34: 'Samsung', Mi_Super_X: 'Xiao Mi'}

# Products and quantities
products = {monitor: 4, keyboard: 13, watch: 38, mouse: 10, door: 7}
```
  
As you see in the example above, ‘Xiao Mi’ or ‘Samsung’ companies have many phones, that is, values are the same in many elements, but the keys are all unique. So, when we refer to the unique key ‘Diamond_s34’, it returns its element ‘Samsung’.
In the example above, in each pair divided by comma, the one on the left is the key and the one on the right is the value of each element.  
You can store any kind of object as a key or as a value in the Hash element.  
```
months = Hash.new
months = {"1": "January", "2": "February", "3": "March"
```
  
# Accessing and Updating Hash elements
To access elements in the Hash, we use square brackets [], as it was in Arrays. We write the key we want to get in the square brackets.  
* If there is such a key in the Hash, then you get its value.
* If there is no such key in the Hash, then that key and its value are added to the Hash.
  
So let's access existing elements and add some new to the Hash.
  
```
# Fruits and prices
fruits = {ananas: 12.7, banana: 4.9}
puts fruits[:ananas]  # 12.7
puts fruits[:apple] # 'nil', because there is no such key yet

# This way we can add new element to the Hash
fruits[:apple] = 3.6
fruits[:lemon] = 5.35

# New Hash {ananas: 12.7, banana: 4.9, apple: 3.6, lemon: 5.35}
puts fruits[:lemon] # 5.35
```
  
If we want to search for a specific element in the Hash, we have two options. We can search for its key or its value. Depending on what we search for, we use corresponding methods for it. These methods return ‘true’ or ‘false’. Otherwise, they let you know whether such key or value exists in the Hash. 
Here they are:  
* **has_key?(key), key?(key)** : Checks whether we have such a key in the Hash.
* **has_value?(value), value?(value)** : Checks whether we have such a value in the Hash.
  
```
countries = {ES: 'Spain', TM: 'Turkmenistan', NZ: 'New Zealand'}
puts countries.has_key?(:ES) # true
puts countries.key?(:GB) # false
puts countries.has_value?('Turkmenistan') # true
puts countries.value?('Great Britain') # false
```
  
# Length/Size of the Hash
As in Arrays, to calculate the number of elements or pairs in Hashes, we use ‘size’ and ‘length’ methods.
```
fruits = {ananas: 12.7, banana: 4.9, apple: 3.6, lemon: 5.35}
puts fruits.length # 4
puts fruits.size   # 4
```

# Add or remove elements from a Hash
We already did this kind of manipulation in one of the examples above to add a new element to a Hash. If we provide a key that is not yet present in the Hash, then we automatically add it as a new value into it. We just have to define its value as well. 
For instance:
```
countries = {ES: 'Spain', TM: 'Turkmenistan'}
puts countries[ES] # 'Spain'
countries[:NZ] = 'New Zealand'
# {ES: 'Spain', TM: 'Turkmenistan', NZ: 'New Zealand'}
```
  
We use ‘delete’ methods to remove an existing element from the Hash. We provide the key of the element to be removed as a parameter to that method.
```
countries = {ES: 'Spain', TM: 'Turkmenistan', NZ: 'New Zealand'}
countries.delete(:ES) # removes pair (ES: 'Spain') 
puts countries[:ES] # nil, because we already removed it.
```
  
# Iterate through Hash elements
You might remember using ‘each’ method to iterate through Array elements. We can use the same methods to iterate through each pair in the Hash.
Let’s take a look at the code below that outputs each pair on a new line.
```
person = {name: 'John', height: 180, weight: 85, hair: 'black'} 
 
person.each do |key, value|   
   puts "John's #{key} = #{value}" 
end
# John's name = John
# John's height = 180
# John's weight = 85
# John's hair = black
```
  
# Getting all the keys or values from the Hash
If we want to print out only the keys or only values from the Hash, then we use these methods:
* **keys**: returns list of Hash keys
* **values**: returns list of Hash values
Let’s take a look at the currencies example:

```
currencies = {USA: 'USD', Turkey: 'TL', Turkmenistan: 'TMM'}
puts currencies.keys # [USA, Turkey, Turkmenistan]
puts currencies.values# ['USD', 'TL', 'TMM']
```

# Conclusion
Hey, friends. We came to the end of the article about Hashes. So now we know a bit more about Ruby PL and one more complex data structure. You might have similarities between Arrays and Hashes and at the same time recognized that they are somewhat completely different.
You get more professional and strong in a battle, as you learn and use more tools. Sometimes I compare it to programming tools. And as we learn and use more tools, we get to write more professional code. So now we have one more tool in our set.
Let’s develop together and write clean and beautiful code. Good luck!