Fork, clone, branch (training), bundle install
By the end of this, developers should be able to:
{}
) and new
constructors.In Ruby, "A Hash is a dictionary-like collection of unique keys and their values". In sharp contrast to JavaScript, Ruby Hashes are not the most general object in the language, but are instances of a specialized class for key/value storage.
A Symbol is a sequence of characters that is stored at most once in any instance of the Ruby interpreter.
In Ruby, strings are compared a character at a time, but symbols are compared by
object_id
. This makes comparing symbols fast and therefore much more
performant than strings when used as keys in a Hash
.
Each of the following pairs of operations are equivalent:
> 'bob'.equal? 'bob'
=> false
> 'bob'.object_id == 'bob'.object_id
=> false
> 'bob'.eql? 'bob'
=> true
> 'bob' == 'bob'
=> true
But all of the following operations are equivalent:
> :bob.equal? :bob
=> true
> :bob.object_id == :bob.object_id
=> true
> :bob.eql? :bob
=> true
> :bob == :bob
=> true
We can create a symbol with arbitrary characters if we surround the characters
with quotes (either :'<characters>'
or '<characters>'.to_sym
):
> :'&foo'.equal? '&foo'.to_sym
=> true
How does this compare to keys in JavaScript?
Let's look at different ways to create a Hash.
> apartment = {}
=> {}
> apartment = Hash.new
=> {}
> apartment = Hash.new('')
=> {}
> apartment[:address]
=> ""
> apartment[:address] = { street: '255 Long Road', city: 'Awesomeville'}
=> {:street=>"255 Long Road", :city=>"Awesomeville"}
> apartment[:bedrooms] = 3
=> 3
> priced_apartment = apartment.merge({rent: 1000})
=> {:address=>{:street=>"255 Long Road", :city=>"Awesomeville"}, :bedrooms=>3, :rent=>1000}
Picking sensible defaults may not always be easy.
Let's use the different forms of Hash::new
to create some hashes in bin/code_along.rb
.
In bin/lab.rb create a hash using the shorthand syntax for
assigning the keys :sq_ft
:pets_allowed
with a type-appropriate value
of your choice. Then assign a default of []
to the hash and make sure that
accessing non-existing keys return the default.
> priced_apartment[:occupants] = []
=> []
> lee = {name: "Lee", age: 24, dog: "Fluffy"}
=> {:name=>"Lee", :age=>24, :dog=>"Fluffy"}
> adrian = {name: "Adrian", age: 25, cat: "Scratchy"}
=> {:name=>"Adrian", :age=>25, :cat=>"Scratchy"}
> priced_apartment[:occupants].push(lee, adrian)
=> [{:name=>"Lee", :age=>24, :dog=>"Fluffy"}, {:name=>"Adrian", :age=>25, :cat=>"Scratchy"}]
> priced_apartment[:occupants][1].delete(:cat)
=> "Scratchy"
> priced_apartment[:rent] += 150
=> 1150
Add roommate Bo to :occupants
in the hash in bin/lab.rb.
Append one or more properties of your choosing to the roommate objects, such as
:job
or :education
.
To get an Array of the keys that have been set in a hash, use Hash#keys
.
> priced_apartment.keys
=> [:address, :bedrooms, :occupants, :rent]
What if we wanted to instantiate our new hash with this default right off the bat? Checkout the Ruby docs on new hashes with default blocks.
Then, in bin/lab.rb
initialize a new hash using Hash.new
with a block that
sets the default value (without using .default
) of all keys to the string
"Sorry, <keyname> does not exist".
Curly braces are not necessary when the last parameter to a function is a hash.
def mad_lib(greeting, opts_hash)
puts greeting
[
"This morning I came to campus and ran into #{opts_hash[:name]}.",
"We talked about #{opts_hash[:noun]},",
"which is a #{opts_hash[:adjective]} subject.",
"We couldn't talk for long though since I had to",
"#{opts_hash[:verb]} to class."
].join(' ')
end
mad_lib('Hello, please enjoy this madlib!', noun: 'rainbows', adjective: 'gritty', verb: 'scoot', name: 'Ric Flair')
# mad_lib('Hello', {
# noun: 'rainbows',
# adjective: 'gritty',
# verb: 'scoot',
# name: 'Ric Flair'
# })