Git Product home page Git Product logo

ruby-repl-testing's Introduction

Manipulating Hashes

Objectives

In this lesson, we'll be taking a closer look at multidimensional, or nested, hashes, iteration and higher level hash methods. We'll go through a few challenges together and then you'll complete the lab on your own.

More On Building Nested Hashes

contacts = {
  "Jon Snow" => {
    name: "Jon",
    email: "[email protected]",
    favorite_icecream_flavors: ["chocolate", "vanilla"]
  },
  "Freddy" => {
    name: "Freddy",
    email: "[email protected]",
    favorite_icecream_flavors: ["strawberry", "cookie dough", "mint chip"]
  }
}

Adding Information to Nested Hashes

Example 1:

Your good buddy Jon Snow has just tried mint chip ice cream for the first time. He loved it a lot and now you need to add "mint chip" to his list of favorite ice creams. We already know how to access the array of ice cream flavors that constitute the value of the :favorite_ice_cream_flavors key:

contacts["Jon Snow"][:favorite_ice_cream_flavors]
#  => ["chocolate", "vanilla"]

How can we add a flavor to the list? Well, :favorite_ice_cream_flavors is an array, we we can use the same syntax as above to access that array along with our old friend, the <<, shovel method, to add an item to the array. Let's take a look:

contacts["Jon Snow"][:favorite_ice_cream_flavors] << "mint chip"

puts contacts
#  => {
  "Jon Snow" => {
    name: "Jon",
    email: "[email protected]",
    favorite_ice_cream_flavors: ["chocolate", "vanilla", "mint chip"]
  },
  "Freddy" => {
    name: "Freddy",
    email: "freddy@mercury.com",
    favorite_ice_cream_flavors: ["strawberry", "cookie dough", "mint chip"]
  }
}

Example 2:

Now let's say that you want to add a whole new kay/value pair to your Jon Snow contact––his address. In a simpler hash with just one level of key value pairs, we've already learned how to add new key/value pairs. Here's a reminder:

hash = {first: "first value!", second: "second value!"}
hash[:third] = "third value!"

puts hash
#  => {first: "first value!", second: "second value!", third: "third value!"}

In a nested hash, we can add brand new key/value pairs very similarly. We just need to first access the level of the hash to which we want to add a key value pair. We want the "Jon Snow" key to include a new key/value pair of his address. Take a look at the implementation below:

contacts["Jon Snow"][:address] = "The Lord Commander's Rooms, The Wall, Westeros"

puts contacts
#  =>
{
"Jon Snow" => {
   :name=>"Jon", :email=>"[email protected]",
   :favorite_ice_cream_flavors=>["chocolate", "vanilla", "mint chip"],
   :address=>"The Lord Commander's Rooms, The Wall, Westeros"},
"Freddy"=> {
   :name=>"Freddy",
   :email=>"[email protected]",
   :favorite_ice_cream_flavors=> ["cookie dough", "mint chip"]
 }
}

Iterating Over Nested Hashes

So far, we've only iterated over hashes that had one level––a series of key/value pairs on a single tier. What happens when we want to iterate over a multidimensional hash like the one above? Let iterate over our nested hash, one level at a time.

We're going to iterate over the first level of our hash like this:

contacts = {
  "Jon Snow" => {
    name: "Jon",
    email: "[email protected]",
    favorite_ice_cream_flavors: ["chocolate", "vanilla", "mint chip"]
  },
  "Freddy" => {
    name: "Freddy",
    email: "[email protected]",
    favorite_ice_cream_flavors: ["strawberry", "cookie dough", "mint chip"]
  }
}

contacts.each do |person, data|
	puts "#{person}: #{data}"
end

This should return:

Jon Snow
{ :name=>"Jon",
  :email=>"[email protected]",
  :favorite_ice_cream_flavors=>["chocolate", "vanilla", "mint chip"]
}

Freddy:
{ :name=>"Freddy",
:email=>"[email protected]",
:favorite_ice_cream_flavors=>["strawberry", "cookie dough", "mint chip"]
}

On the first level, the keys are our contacts' names: Jon Snow and Freddy, and our values are the hashes that contain a series of key/value pairs describing them.

Let's iterate over the second level our our contacts hash. In order to access the key/value pairs of the second tier (i.e. the name, email and other data about each person), we need to iterate down into that level. So, we pick up where we left off with the previous iteration and we keep going:

contacts.each do |person, data|
	#at this level, "person" is Jon Snow or Freddy and "data" is a hash of key/value pairs
	#to iterate over the "data" hash, we can use the following line:

	data.each do |attribute, value|
		puts "#{attribute}: #{value}
	end
end

That should output the following:

name: Jon
email: jon_snow@thewall.we
favorite_ice_cream_flavors: ["chocolate", "vanilla", "mint chip"]

name: Freddy
email: freddy@mercury.com
favorite_ice_cream_flavors: ["strawberry", "cookie dough", "mint chip"]

Now it's your turn. In the challenge below, you'll be removing and item from an array in multidimensional hash.

Let's take is one step further and print out just the favorite ice cream flavors. Once again, we'll need to iterate down into that level of the hash, then we can access the favorite ice cream array and print out the flavors:

contacts.each do |person, data|
	#at this level, "person" is Jon Snow or Freddy and "data" is a hash of key/value pairs
	#to iterate over the "data" hash, we can use the following line:

	data.each do |attribute, value|
		#at this level, "attribute" is describes the key of :name, :email or fav. flavor
		#we need to first check and see if the key is :favorite_ice_cream_flavors.
		#if it is, that means the VALUE is an array that we can iterate over to print out each element

		if attribute == :favorite_ice_cream_flavors
			value.each do |flavor|
				# here, each index element in an ice cream flavor string
				puts "#{flavor}"
			end
		end
	end
end

This should output:

chocolate
vanilla
mint chip
strawberry
cookie dough
mint chip

Now it's your turn! You're going to iterate through the levels of this hash to operate on one of the ice cream flavor arrays.

Reminder: Iterating through nested hashes is hard, and (I'm pretty sure) you are not psychic. Meaning, you can't necessarily predict with perfect clarity what the key/value pair is at a certain level of the hash. Using binding.pry when you are iterating in upcoming labs to make sure you understand what the key/value pair is that you are iterating over.

???

Code Challenge I: Manipulating Nested Hashes

Your good buddy Freddy Mercury has recently developed a strawberry allergy. You need to delete "strawberry" from his list of favorite ice_creams. Iterate over the below array and when you reach the key of :favorite_ice_cream_flavors, check to see if the array contains strawberry, if it does, remove it. Hint: use the delete_if method to eliminate strawberry from the appropriate array.

contacts = {
  "Jon Snow": {
    name: "Jon",
    email: "[email protected]",
    favorite_ice_cream_flavors: ["chocolate", "vanilla", "mint chip"]
  },
  "Freddy": {
    name: "Freddy",
    email: "[email protected]",
    favorite_ice_cream_flavors: ["strawberry", "cookie dough", "mint chip"]
  }
}

?: Which code snippet produces the desired result?

(x)

contacts.each do |person, data|
  if flavors = data[:favorite_ice_cream_flavors]
    flavors.delete_if { |flavor| flavor == "strawberry" }
  end
end

( )

contacts.each do |person, flavors|
  flavors.delete_if { |flavor| flavor == 'strawberry' }
end

( )

contacts.each do |person, data|
  data.each do |k, v|
    v.delete_if { |f| f == 'strawberry' }
  end
end

Higher Level Hash Methods

In a previous lab, you were asked to iterate over a hash and collect the key that pointed to the lowest value. We asked you not to use some of the higher level hash methods there. Now, we're going to learn a few tricks that make a task like that much easier.

.values

You can collect all of the values in a hash with the .values method:

family_members = {mom: "Victoria", dad: "Richard", sister: "Zoe"}

family_members.values
#  => ["Victoria", "Richard", "Zoe"]

We can see that the .values method returns an array of the values of the keys in the hash.

.keys

This method, not surprisingly, returns an array of the keys in the hash that you call it on:

family_members = {mom: "Victoria", dad: "Richard", sister: "Zoe"}

family_members.keys
#  => [:mom, :dad, :sister]

.min

You can use the .min method on a hash to return the key/value pair that contains that lowest value:

food_items = {apples: 45, pears: 12}

food_items.min
#  => [:apples, 45]

These are only a few of the many helpful methods out there. Be there to check out the Ruby Docs on Hashes to learn more.

Let's practice before you move on to the next lab:

Code Challenge II: Manipulating Nested Hashes

Below we have a nested hash of grocery items. Use the .values method to collect all of the values of the grocery type keys (:dairy, :meat, etc). The end return should be one-dimensional array of groceries that only includes actual foods ("milk", "carrots").

Hint: What happens when you call .values on a nested hash? What is the return value? How can you flatten an array of arrays? Try out your code in IRB to help you solve this one.

groceries = {
   dairy: ["milk", "yogurt", "cheese"],
   vegetable: ["carrots", "broccoli", "cucumbers"],
   meat: ["chicken", "steak", "salmon"],
   grains: ["rice", "pasta"]
}

?: What snippet will produce the correct result?

( )

groceries.values

(x)

groceries.values.flatten

( )

groceries.flatten

???

Resources:

View Manipulating Hashes on Learn.co and start learning to code for free.

ruby-repl-testing's People

Contributors

annjohn avatar loganhasson avatar maclover7 avatar mikespangler avatar pletcher avatar rrcobb avatar sophiedebenedetto avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.