{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "infrared-classification",
   "metadata": {},
   "source": [
    "  <!--\n",
    "title: Python Programming: Dictionaries\n",
    "type: lesson\n",
    "duration: 00:30\n",
    "creator: Susi Remondi\n",
    "Private gist location: xxxxxx\n",
    "Presentation URL: xxxxx\n",
    "-->\n",
    "\n",
    "\n",
    "<h1>Python Programming: Dictionaries</h1>\n",
    "\n",
    "\n",
    "<!--\n",
    "\n",
    "\n",
    "## Overview\n",
    "This lesson introduces students to the concept of dictionaries. It begins with simple creation, printing, and changing values. It ends with a series of You Do exercises to build students' confidence.\n",
    "\n",
    "## Important Notes or Prerequisites\n",
    "This is the beginning of the object-oriented programming unit. Take a few minutes before starting this lesson to recap the idea of lists and storing elements in objects.\n",
    "\n",
    "## Learning Objectives\n",
    "In this lesson, students will:\n",
    "- Perform common dictionary actions.\n",
    "- Build more complex dictionaries.\n",
    "\n",
    "## Duration\n",
    "30 minutes\n",
    "\n",
    "### Timing note:\n",
    "- If there's time remaining at the end, it'd be great to give exercises involving multiple types of values in dictionaries.\n",
    "- There is, in the `xx-additional-exercises` folder in the parent folder, a reverse lookup challenge that you should assign in class if there's time. If not, assign it as homework.\n",
    "\n",
    "## Suggested Agenda\n",
    "\n",
    "| Time | Activity |\n",
    "| --- | --- |\n",
    "| 0:00 - 0:03 | Welcome |\n",
    "| 0:03 - 0:12 | Introducing Dictionaries |\n",
    "| 0:12 - 0:27 | Complex Thoughts |\n",
    "| 0:27 - 0:30 | Summary |\n",
    "\n",
    "## In Class: Materials\n",
    "- Projector\n",
    "- Internet connection\n",
    "- Python 3\n",
    "\n",
    "-->\n",
    "\n",
    "---\n",
    "\n",
    "## Learning Objectives\n",
    "\n",
    "*After this lesson, you will be able to:*\n",
    "\n",
    "- Perform common dictionary actions.\n",
    "- Build more complex dictionaries.\n",
    "\n",
    "---\n",
    "\n",
    "## Kicking Off Unit 3\n",
    "\n",
    "In Unit 2, we worked with conditionals and control flow which validated our user input and formatted print strings.\n",
    "\n",
    "Unit 3 will take the functionality from unit 2 and _refactor_ (change the structure of) it into a `class`.\n",
    "\n",
    "- A `class` is an object that contains `methods` - functionality that operates _on_ the object\n",
    "- We'll be structuring code in a `class` as a way to group common functionality together\n",
    "- You already have one object down! Lists are an object with `methods` like `append()` and `pop()`\n",
    "\n",
    "Ready? Let's go!\n",
    "\n",
    "---\n",
    "\n",
    "## Introducing Dictionaries\n",
    "\n",
    "Think about dictionaries — they're filled with words and definitions that are paired together.\n",
    "\n",
    "Programming has a dictionary object just like this!\n",
    "\n",
    "- Dictionaries hold keys (words) and values (the definitions).\n",
    "- In a real dictionary, you can look up a word and find the definition. In a Python dictionary, you can look up a key and find the value.\n",
    "\n",
    "\n",
    "---\n",
    "\n",
    "## Introducing Dictionaries\n",
    "\n",
    "![](https://s3.amazonaws.com/ga-instruction/assets/python-fundamentals/dictionary.png)\n",
    "\n",
    "\n",
    "- We can have an object that holds keys (`'puppy'`, `'pineapple'`, `'tea'`) and their values (`'furry, energetic animal'`, etc.).\n",
    "\n",
    "---\n",
    "\n",
    "## Declaring a Dictionary\n",
    "\n",
    "Dictionaries in programming are made of **key-value pairs**.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "better-quebec",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Here's the syntax:\n",
    "name_of_dictionary = {\"Key1\": \"Value\", \"Key2\": \"Value\", \"Key3\": \"Value\"}\n",
    "print(name_of_dictionary[key_to_look_up])\n",
    "# Prints the value\n",
    "\n",
    "# And in action...\n",
    "my_dictionary = {\"Puppy\": \"Furry, energetic animal\", \"Pineapple\": \"Acidic tropical fruit\", \"Tea\": \"Herb-infused drink\"}\n",
    "\n",
    "print(my_dictionary)\n",
    "# Prints the whole dictionary\n",
    "print(my_dictionary[\"Puppy\"])\n",
    "# => Prints Puppy's value: \"Furry, energetic animal\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "decimal-collection",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## We Do: Dictionaries and Quick Tips\n",
    "\n",
    "The order of keys you see printed may differ from how you entered them. That's fine!\n",
    "\n",
    "You can't have the same key twice. Imagine having two \"puppies\" in a real dictionary! If you try, the last value will be the one that's kept.\n",
    "\n",
    "What's more, printing a key that doesn't exist gives an error.\n",
    "\n",
    "Let's create a dictionary together.\n",
    "\n",
    "- Keys can be a string or integer. \n",
    "- You can look up any key — but not the value (just like a real dictionary!).\n",
    "- Use meaningful keys: `my_zip_code` is better than `some_numbers`.\n",
    "- The items that are returned when you access a dictionary come in any order they please.\n",
    "  - This doesn't really matter that much, however, because the typical use case for a dictionary is when you know the exact key for the value you're looking for.\n",
    "  - But, you should never count on the contents of a dictionary being in any order at all."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "approximate-indie",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "impressive-strength",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## We Do: Dictionary Syntax\n",
    "\n",
    "\n",
    "What if a value changes? We can reassign a key's value: `my_dictionary[\"Puppy\"] = \"Cheerful\"`.\n",
    "\n",
    "What if we have new things to add? It's the same syntax as changing the value, just with a new key:\n",
    "`my_dictionary[\"Yoga\"] = \"Peaceful\"`.\n",
    "\n",
    "- Changing values is case sensitive — be careful not to add a new key!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "involved-paragraph",
   "metadata": {},
   "outputs": [],
   "source": [
    "my_dictionary = {\"Puppy\": \"Furry, energetic animal\", \"Pineapple\": \"Acidic tropical fruit\", \"Tea\": \"Herb-infused drink\"}\n",
    "\n",
    "# change a key's value\n",
    "\n",
    "print(my_dictionary)\n",
    "\n",
    "# add a key\n",
    "\n",
    "print(my_dictionary)\n",
    "\n",
    "# Remember that keys are case sensitive!\n",
    "\n",
    "print(my_dictionary)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "constitutional-norwegian",
   "metadata": {},
   "source": [
    "\n",
    "</aside>\n",
    "\n",
    "\n",
    "---\n",
    "\n",
    "## Quick Review: Dictionaries\n",
    "\n",
    "We can:\n",
    "\n",
    "- Make a dictionary.\n",
    "- Print a dictionary.\n",
    "- Print one key's value.\n",
    "- Change a key's value.\n",
    "\n",
    "Here's a best practice: Declare your dictionary across multiple lines for readability. Which is better?\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "continued-gauge",
   "metadata": {},
   "outputs": [],
   "source": [
    "# This works but is not proper style.\n",
    "my_dictionary = {\"Puppy\": \"Furry, energetic animal\", \"Pineapple\": \"Acidic tropical fruit\", \"Tea\": \"Herb-infused drink\"}\n",
    "\n",
    "# Do this instead!\n",
    "my_dictionary = {\n",
    "  \"Puppy\": \"Furry, energetic animal\",\n",
    "  \"Pineapple\": \"Acidic tropical fruit\",\n",
    "  \"Tea\": \"Herb-infused drink\"\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "actual-presentation",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## Discussion: Collection Identification Practice\n",
    "\n",
    "What are `a` and `b` below?:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "smooth-present",
   "metadata": {},
   "outputs": [],
   "source": [
    "# What object is this?\n",
    "\n",
    "collection_1 = [3, 5, 7, \"nine\"]\n",
    "\n",
    "# What object is this?\n",
    "collection_2 = {\"three\": 3, \"five\": 5, 9: \"nine\"}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "comfortable-mentor",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## Looping Through Dictionaries\n",
    "\n",
    "\n",
    "We can print a dictionary with `print(my_dictionary)`, but, like a list, we can also loop through the items with a `for` loop:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "drawn-investigation",
   "metadata": {},
   "outputs": [],
   "source": [
    "my_dictionary = {\n",
    "  \"Puppy\": \"Furry, energetic animal\",\n",
    "  \"Pineapple\": \"Acidic tropical fruit\",\n",
    "  \"Tea\": \"Herb-infused drink\"\n",
    "}\n",
    "\n",
    "for key in my_dictionary:\n",
    "    print(my_dictionary[key])\n",
    "    \n",
    "print()\n",
    "\n",
    "for key in my_dictionary:\n",
    "    print(key, \":\", my_dictionary[key])\n",
    "    \n",
    "print()\n",
    "    \n",
    "# you can also loop through just the values\n",
    "for value in my_dictionary.values():\n",
    "    print(value)\n",
    "    \n",
    "print()\n",
    "    \n",
    "# or loop through the keys AND values using .items()\n",
    "for key, value in my_dictionary.items():\n",
    "    print(key, \":\", value)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "foreign-application",
   "metadata": {},
   "source": [
    "</aside>\n",
    "\n",
    "---\n",
    "\n",
    "## Partner Exercise: Dictionary Practice\n",
    "\n",
    "You know the drill: Grab a partner and pick a driver!\n",
    "\n",
    "Write code that declares a dictionary called `my_name`.\n",
    "\n",
    "- Add a key for each letter in your name with a value of how many times that letter appears.\n",
    "\n",
    "As an example, here is the dictionary you'd make for `\"Callee\"`:\n",
    "\n",
    "`my_name = {\"c\": 1, \"a\": 1, \"l\": 2, \"e\": 2}`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "invisible-lodging",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "married-headline",
   "metadata": {},
   "source": [
    "\n",
    "Write a loop that prints the dictionary, but formatted.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "intended-nightmare",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Example output: The letter l appears in my name 2 times.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "administrative-accounting",
   "metadata": {},
   "source": [
    "\n",
    "**Bonus (if you have time)**: If it's only one time, instead print `The letter l appears in my name once`. If it's only two times, instead print `The letter l appears in my name twice.`\n",
    "\n",
    "---\n",
    "\n",
    "## Partner Exercise: Most Popular Word\n",
    "\n",
    "With the same partner, switch who's driving.\n",
    "\n",
    "Write a function, `max_val()`, that takes a dictionary and returns the\n",
    "maximum value of any of the keys in the dictionary. Assume that the input\n",
    "dictionary's values will always be non-null integers.\n",
    "\n",
    "\n",
    "**Hints:**\n",
    "\n",
    "- When looping over a dictionary, does Python loop over the keys or the\n",
    "    values? How do you make it loop over values?\n",
    "- Bonus: have the function return the maximum value, _and_ the key\n",
    "    associated with that value\n",
    "\n",
    "For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "coupled-situation",
   "metadata": {},
   "outputs": [],
   "source": [
    "input_dict = {\n",
    "    'a': 2,\n",
    "    'b': 3,\n",
    "    'c': 1\n",
    "}\n",
    "\n",
    "# function defenition\n",
    "\n",
    "\n",
    "\n",
    "max_val(input_dict)\n",
    "# returns 3"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "mineral-offense",
   "metadata": {},
   "source": [
    "</aside>\n",
    "\n",
    "---\n",
    "\n",
    "## Other Values\n",
    "\n",
    "We're almost there! Let's make this more complex.\n",
    "\n",
    "In a list or a dictionary, anything can be a value.\n",
    "- This is a good reason to split dictionary declarations over multiple lines!\n",
    "- Think about how you would access a particular element inside each object (e.g. the last item of the list for the \"WA\" key in the `other_values_in_a_dictionary` dict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "intensive-exhibition",
   "metadata": {},
   "outputs": [],
   "source": [
    "other_values_in_a_dictionary = {\n",
    "  \"CA\": {\"key1\" : \"value 1\",\n",
    "        \"another_key\" : \"a value\",\n",
    "        \"Joe\" : \"Even more dictionary!\"\n",
    "        },\n",
    "  \"WA\": [\"Trevor\", \"Courtney\", \"Brianna\", \"Kai\"],\n",
    "  \"NY\": \"Just Tatyana\"\n",
    "}\n",
    "\n",
    "print(\"Here's a dictionary and list in a dictionary:\", other_values_in_a_dictionary)\n",
    "\n",
    "print(\"----------\")\n",
    "\n",
    "other_values_in_a_list = [\n",
    "  \"a value\",\n",
    "  {\"key1\" : \"value 1\", \"key2\" : \"value 2\"},\n",
    "  [\"now\", \"a\", \"list\"]\n",
    "  ]\n",
    "print(\"Here's a list and dictionary in a list:\", other_values_in_a_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cross-cleaners",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "sealed-basis",
   "metadata": {},
   "source": [
    "\n",
    "</aside>\n",
    "\n",
    "---\n",
    "\n",
    "## Summary and Q&A\n",
    "\n",
    "Dictionaries:\n",
    "\n",
    "- Are another kind of collection, instead of a list.\n",
    "- Use **keys** to access **values**, not indices!\n",
    "- Should be used instead of lists when:\n",
    "  - You don't care about the order of the items.\n",
    "  - You'd prefer more meaningful keys than just index numbers.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "champion-muscle",
   "metadata": {},
   "outputs": [],
   "source": [
    "my_dictionary = {\n",
    "  \"Puppy\": \"Furry, energetic animal\",\n",
    "  \"Pineapple\": \"Acidic tropical fruit\",\n",
    "  \"Tea\": \"Herb-infused drink\"\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "executive-academy",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "## Optional Practice: Reverse Lookup\n",
    "\n",
    "Finding the value from a key is easy: `my_dictionary[key]`. But, what if you only have the value and want to find the key?\n",
    "\n",
    "You task is to write a function, `reverse_lookup()`, that takes a dictionary and a value and returns the corresponding key.\n",
    "\n",
    "For example:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "verified-photograph",
   "metadata": {},
   "outputs": [],
   "source": [
    "state_capitals = {\n",
    "  \"Alaska\" : \"Juneau\",\n",
    "  \"Colorado\" : \"Denver\",\n",
    "  \"Oregon\" : \"Salem\",\n",
    "  \"Texas\" : \"Austin\"\n",
    "  }\n",
    "\n",
    "# function definition\n",
    "\n",
    "\n",
    "\n",
    "print(reverse_lookup(\"Denver\"))\n",
    "# Prints Colorado\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "floral-pierce",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
