Introduction
In this article, we'll keep exploring hashes and we'll discover what symbols are. For a refresher on hashes, I wrote this.
Introduction to nil
In Ruby, nil is a way to say that a value doesn't exist. So, if we have a Hash and we try to access a value that doesn't exist:
my_hash = {
"name" => "Damien",
"age" => 26,
"nationality": "French"
}
puts my_hash["lastName"] # puts nothing, because nil. lastName key doesn't exist
No error thrown, Ruby just tells you that nothing exists there by telling you... nothing :D
However, you can specify a default value in a Hash. That default value will be returned instead of nil when Ruby doesn't find a value inside a Hash:
with_default = Hash.new("No value found here!!!")
puts with_default["name"] # puts "No value found here!!!"
puts with_default[42] # puts "No value found here!!!"
Symbols
Let's start with the syntax. Symbols always start with a colon : and they must be a valid variable name:
my_symbol = :this_is_a_symbol
Symbols can be used as hash keys or to reference a method's name.
Hash's key
Symbols are a good use for hash keys because they are immutable. You can't change a symbol once its defined. Only one copy of a symbol can exist at one time, so they do not consume a lot of memory. These two reasons makes symbols as keys faster than strings as keys.
my_hash = {
:one => "One",
:a_symbol => 42,
:boom => true
}
puts my_hash
# {:one=>"One", :a_symbol=>42, :boom=>true}
Converting between symbols and strings.
Ruby provides methods to convert a symbol to a string and vice versa. The method .to_s converts a symbol to a string while .to_sym does the opposite. The method .intern does the same thing than .to_sym
puts :this_is_my_shiny_symbol.to_s # this_is_my_shiny_symbol
puts "look_at_this_string".to_sym # :look_at_this_string
puts "HelloWorld".intern # :HelloWorld
Hash rocket syntax
You saw that we used a => between the key and the value in a hash. This is called the hash rocket syntax. However, you can also use a shorter syntax. To do so, remove the => and place the colon at the end of the symbol. The syntax resembles a javascript object now:
symbols_as_keys = {
one: "two",
three: "four"
}
The keys are still symbols. However, this syntax doesn't work with strings as keys.
Be more selective
We can grab a value from a hash when we have its associated key. But how would we filter a hash to only retrieve values that meet some criteria? We could use .select
restaurant_ratings = {
soleia: 6,
auberge_du_printemps: 3,
pauls: 4,
olive_garden: 7
}
Let's use select to filter restaurants with a rating strictly superior to 5.
puts restaurant_ratings.select{ |restaurant, rating|
rating > 5
}
# {:soleia=>6, :olive_garden=>7}
Now, let's get the restaurants where the rating is equal to 3
puts restaurant_ratings.select{ |restaurant, rating|
rating == 3
}
# {:auberge_du_printemps=>3}`
Just the keys? Or just the values
Because Ruby is awesome, you do not need to iterate over keys AND values if you don't need one of them. With .each_key, you'll iterate only over the keys and with .each_value, you will get only the values:
restaurant_ratings.each_key{|k| puts k}
# soleia
# auberge_du_printemps
# pauls
# olive_garden
restaurant_ratings.each_value{|v| puts v}
# 6
# 3
# 4
# 7
Top comments (2)
Another, fetch(key, default) is a good method for hash.
Snakecase?