Quick Tip: The Many Ways to Create a Hash in Ruby

Glenn Goodrich
Glenn Goodrich
Share

As Rubyists, we use Hashes for everything. They are just so danged easy and useful. I mean, how often do you need something keyed to something else? A lot, if you’re like me. For example, I have four (4) kids, which is a lot. I like to carry around a Hash like this one so I don’t forget their names:

$> kids = {1: "Logan", 2: "Emma", 3: "Lily", 4: "Becca"}

Well, this is how I started, but that is little more than a glorified array. Plus, I found myself needing all kinds of information about them, so I changed the hash:

$> kids = {logan: { gender: :boy, dob: Date.new(2000, 12,24), sports: [:soccer], favorite: false } ... }

You get the idea. This Hash has served me well for quite some time, but I thought I’d look into some different ways to create this hash to see if I could make it even more useful.

This is Your Grandparents’ Hash Creation

OK, let’s knock out the normal, boring ways to create a Hash. First, there’s what I did above, which is the “shorthand” syntax to create a Hash:

$> kids = {logan: { gender: :boy, dob: Date.new(2000, 12,24), sports: [:soccer], favorite: false } ... }

While it’s not sexy or exciting, it is the way 99.99999% of Hashes are created in Ruby. It kinda looks like JSON. In fact, I often wonder if Hashes and JSON objects all hang out together at some places called Value Bar (it’s in the Keys, get it?) and intermingle. But, I digress.

The other yawn-inducing method of creating a Hash is by calling the .new method:

$> kids = Hash.new
=> {}

That gives us an empty Hash. Were you expecting me to do this?

$> hash = Hash.new(logan: {...})

If you were then, WOW, are you in for a surprise! Hash.new isn’t as boring as you think.

Everything new is Fun Again

Hash.new adds some pizazz, nay flare, nay je ne sais quoi, to Hash creation. In the above example, we still get an empty Hash:

$> kids = Hash.new(logan: {...})
=> {}

But, now we get a new feature in the form of a default value. What this means is, if you ask the Hash to give you the value for a key that is not in the Hash, you’ll get the thing you passed to .new. Here’s how I improved my kids Hash with this feature:

$> kids = Hash.new({yours: false, send_them_home: true})
=> {}
$> kids[:colin]
=> {:yours=>false, :send_them_home=>true}

So, now, when Jill ({ wife: true, birthday: [elided], right: true}) says a kid’s name and that kid is not mine, I get some solid information and instruction on what to do. Sweet! By the way, you can see the default object of a hash by calling #default:

$> kids.default
=> {:yours=>false, :send_them_home=>true}

OR, you can override the default on a hash by calling hash.default = <the object>:

$> kids.default = {yours: false, embarrass: false }
=> {:yours=>false, :embarrass=>false}

But wait! There’s more! You can also pass a block to .new which will be run every time you ask for a key that is not in the Hash:

$> kids = Hash.new do |hash, key|
$>   puts "This is not your kid!"
$>   puts "Don't curse in front of them!"
$>   hash[key] = {yours: false, send_them_home: true}
$> end
=> {}
$> kids[:taylor]
This is not your kid!
Don't cuss in front of them!
 => {:yours=>false, :send_them_home=>true}

Excellent. Again, I have tapped into some of the lesser-known Hash initialization features to supply myself with great information. Notice, by the way, that when I pass a block I have to also store the key and value in the hash manually. If I don’t, the block will get run every time I access the same missing key. Also, just like you can override the default object for a Hash, you can override the default_proc:

$> kids.default_proc
  => #<Proc:0x007fc1eb2d7f80@(irb):15>
$> kids.default_proc = -> (hash, key) { puts "Find an adult" }

Keep Hash Creation Weird

For completeness sake, I’ll mention a couple of other ways to create a Hash. I am 100% sure these are completely useless and no one has ever used them in the history of Ruby programming.

Weird Hash-bracket method #1:

$> other_peoples_kids = Hash[ "colin", {friend_of: :logan, nerdy: true}, "taylor", {friend_of: :lily, annoying: true}]
 => {"colin"=>{:friend_of=>:logan, :nerdy=>true}, "taylor"=>{:friend_of=>:lily, :annoying=>true}}

So, you pass an array with an even number of items and that freak Hash splits them into key-value pairs.

Weird Hash-bracket method #2:

$> kids_interests = Hash[[[:logan, [:soccer, :pokemon]], [:emma, [:cheer, :not_mowing_the_lawn]]]]
 => {:logan=>[:soccer, :pokemon], :emma=>[:cheer, :not_mowing_the_lawn]}

Here, passing in an array of 2-element arrays is converted into a Hash. Seriously, who came up with this?

Weird Hash-bracket method #3:

$> kids_favorite_foods = Hash["login"=>"wings", "emma"=>"pizza", "lily"=>"airheads", "becca"=>"unknown"]
  => {"login"=>"wings", "emma"=>"pizza", "lily"=>"airheads", "becca"=>"unknown"}

Apparently, if I pass in a Hash to Hash[] I get a Hash. This is the Hash equivalent of eating corn.

These bracket methods are so odd that I picture the bad Hashes hanging out at the Value Bar “bracketing” to get high. Or something.

Friends Don’t Let Friends Bracket and Code

Well, that’s it for today’s Quick Tip. I hope you learned something about creating Hashes and/or my children. Speaking of which, the kids are all out so I am going to head to the pub for some bracketing. Good day!

Frequently Asked Questions (FAQs) about Creating a Hash in Ruby

What is a Hash in Ruby and why is it important?

A Hash is a built-in data structure in Ruby that stores key-value pairs. It is similar to an array, but instead of using integers to index or access the data, you can use any object. This makes Hashes incredibly flexible and useful for storing and organizing data. They are important because they allow you to quickly look up values using unique keys, making data retrieval efficient and fast. Hashes are widely used in Ruby and understanding them is crucial for any Ruby developer.

How do I create a Hash in Ruby?

Creating a Hash in Ruby is straightforward. You can create a Hash by using the new method of the Hash class, or by using curly braces {}. Here’s an example of creating a Hash using the new method:
hash = Hash.new
And here’s an example of creating a Hash using curly braces:
hash = {}
You can also initialize a Hash with default values. For example:
hash = Hash.new(0)
This will create a new Hash where the default value for any key is 0.

How do I add elements to a Hash in Ruby?

You can add elements to a Hash in Ruby by using the assignment operator (=). You specify the key and the value you want to store. Here’s an example:
hash = {}
hash["key"] = "value"
In this example, “key” is the key and “value” is the value. You can use any object as a key or value.

How do I access elements in a Hash in Ruby?

You can access elements in a Hash in Ruby by using square brackets [] and specifying the key. Here’s an example:
hash = {"key" => "value"}
puts hash["key"]
This will output “value”. If you try to access a key that does not exist in the Hash, it will return nil.

How do I remove elements from a Hash in Ruby?

You can remove elements from a Hash in Ruby by using the delete method. You specify the key of the element you want to remove. Here’s an example:
hash = {"key" => "value"}
hash.delete("key")
This will remove the key-value pair with the key “key” from the Hash.

How do I iterate over a Hash in Ruby?

You can iterate over a Hash in Ruby by using the each method. The each method takes a block of code and executes it for each key-value pair in the Hash. Here’s an example:
hash = {"key1" => "value1", "key2" => "value2"}
hash.each do |key, value|
puts "#{key}: #{value}"
end
This will output:
key1: value1
key2: value2

Can a Hash in Ruby have duplicate keys?

No, a Hash in Ruby cannot have duplicate keys. If you try to add a key-value pair with a key that already exists in the Hash, it will overwrite the existing value with the new one.

Can a Hash in Ruby have duplicate values?

Yes, a Hash in Ruby can have duplicate values. The uniqueness constraint only applies to keys, not values.

How do I check if a Hash in Ruby contains a specific key?

You can check if a Hash in Ruby contains a specific key by using the has_key? method. Here’s an example:
hash = {"key" => "value"}
puts hash.has_key?("key")
This will output true if the Hash contains the key “key”, and false otherwise.

How do I merge two Hashes in Ruby?

You can merge two Hashes in Ruby by using the merge method. Here’s an example:
hash1 = {"key1" => "value1"}
hash2 = {"key2" => "value2"}
merged_hash = hash1.merge(hash2)
The merged_hash will now contain {“key1” => “value1”, “key2” => “value2”}. If there are duplicate keys in the two Hashes, the value from the second Hash will overwrite the value from the first Hash.