Skip to content

Hashes

Hashes are dictionary style collections that uses key and value pair. There are also known as associative arrays in other languages.

Creating Hashes

They are two ways to create a hash in Ruby.

Create Hash using {}

We can create an empty hash using the {} character as follows :

2.2.5 :133 > hash = {}
 => {}
2.2.5 :134 > hash.class
 => Hash

Create Hash using Hash.new

We can also create a hash by calling the new method on the Hash type as follows :

2.2.5 :135 > hash = Hash.new
 => {}
2.2.5 :136 > hash.class
 => Hash

Creating with string keys

We can use strings as keys for the hashes as follows :

2.2.5 :137 > p = {"name" => "Joseph", "company" => "Peruzal"}
 => {"name"=>"Joseph", "company"=>"Peruzal"}

Creating a hash using symbols for keys

Instead of using strings, we can use symbols for the keys of the hash as follows :

2.2.5 :140 > p = { name: "Joseph", company: "Peruzal" }
 => {:name=>"Joseph", :company=>"Peruzal"}

The longer way of using symbols is as follows :

2.2.5 :142 > p = { :name => "Joseph", :company => "Peruzal" }
 => {:name=>"Joseph", :company=>"Peruzal"}

The shorter way will not work with numeric keys.

You can randomly add more keys to the hash by using the [] symbols as follows :

2.2.5 :142 > p = { :name => "Joseph", :company => "Peruzal" }
 => {:name=>"Joseph", :company=>"Peruzal"}
2.2.5 :143 > p[:location] = "Cape Town"
 => "Cape Town"
2.2.5 :144 > p
 => {:name=>"Joseph", :company=>"Peruzal", :location=>"Cape Town"}

Getting a count of key

We can use the count method to find the number of keys within a hash as follows :

2.2.5 :144 > p
 => {:name=>"Joseph", :company=>"Peruzal", :location=>"Cape Town"} 
2.2.5 :145 > p.count

Check fo existence of keys

We can check for the existence of keys within a hash with the has_key? methods as follows :

2.2.5 :147 > p.has_key? :company
 => true

Alternatively we can check if a value exists using the has_value? method as follows :

2.2.5 :148 > p.has_value? "Joseph"
 => true

Sort keys

By default the hash keys are unordered since we can access them directly, we can use the sort method to put the keys in alphabetical order as follows :

 => {:name=>"Joseph", :company=>"Peruzal", :location=>"Cape Town"}
2.2.5 :150 > p.sort
 => [[:company, "Peruzal"], [:location, "Cape Town"], [:name, "Joseph"]]

Accessing Hash elements

Hash elements are accessed in a similar way as with the arrays, the different is that in a hash we will use a key instead of an index as in arrays. We use the [] to access hash elements as follows :

2.2.5 :151 > p
 => {:name=>"Joseph", :company=>"Peruzal", :location=>"Cape Town"} 
2.2.5 :152 > p[:name]
 => "Joseph"

Selecting key and values

We can use the select method to return the key/value pairs of a hash as follows :

2.2.5 :157 > p.select {|key,value| value == "Joseph"}
 => {:name=>"Joseph"}

Looping Through Hash elements

We can loop through the key/value pair of hash elements using the each method as follows :

2.2.5 :158 > p.each {|key,value| p "#{key} #{value}"}
"name Joseph"
"company Peruzal"
"location Cape Town"
 => {:name=>"Joseph", :company=>"Peruzal", :location=>"Cape Town"}

Loop through each value pair

We can instead loop through each value pair using the each_value method as follows :

2.2.5 :159 > p.each_value {|v| p v}
"Joseph"
"Peruzal"
"Cape Town"
 => {:name=>"Joseph", :company=>"Peruzal", :location=>"Cape Town"}

Loop through each key

We can also loop through the keys using the each_key as follows :

2.2.5 :160 > p.each_key {|k| p k}
:name
:company
:location
 => {:name=>"Joseph", :company=>"Peruzal", :location=>"Cape Town"}

Clearing hashes

We can use the clear method to clear the contents of the hash as follows :

2.2.5 :161 > p.clear
 => {}

Check if hash if empty

We can use the empty? method to check if the hash is empty of not as follows :

2.2.5 :162 > p.empty?
 => true

Remove keys

We can remove keys at the beginning of the hash by using the shift method as follows :

2.2.5 :165 > p
 => {:name=>"Joseph", :company=>"Peruzal"}
2.2.5 :166 > p.shift
 => [:name, "Joseph"]
2.2.5 :167 > p
 => {:company=>"Peruzal"}

Merge hashes

We can use the merge method to join two hashes together as follows :

2.2.5 :179 > person = { first_name: "Joseph", last_name: "Kandi" }
 => {:first_name=>"Joseph", :last_name=>"Kandi"} 
2.2.5 :180 > company = { name: "Peruzal", location: "Cape Town" }
 => {:name=>"Peruzal", :location=>"Cape Town"} 
2.2.5 :181 > person.merge(company)
 => {:first_name=>"Joseph", :last_name=>"Kandi", :name=>"Peruzal", :location=>"Cape Town"} 

Exercise

  1. Choose a random value using a weighted value from a list. The higher the value, the higher the chances of choosing the same value. Assign a weight to each value. E.g :
marbles = { :black => 51, :white => 17 }
3.times { puts choose_weighted(marbles) }
# black
# white
# black

Solution

  1. The following is one way of implementing it :
def choose_weighted(weighted)
    sum = weighted.inject(0) do |sum, item_and_weight|
        sum += item_and_weight[1]
    end
    target = rand(sum)
    weighted.each do |item, weight|
        return item if target <= weight
        target -= weight
    end
end

lottery_probabilities = { "You've wasted your money!" => 1000,
                              "You've won back the cost of your ticket!" => 50,
                              "You've won two shiny zorkmids!" => 20,
                              "You've won five zorkmids!" => 10,
                              "You've won ten zorkmids!" => 5,
                              "You've won a hundred zorkmids!" => 1 }
# Let's buy some lottery tickets.
5.times { puts choose_weighted(lottery_probabilities) }