{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "# Chapter 8: Mappings & Sets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Coding Exercises" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Read [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_00_content.ipynb) of the book. Then, work through the exercises below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Working with Nested Data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's write some code to analyze the historic soccer game [Brazil vs. Germany](https://en.wikipedia.org/wiki/Brazil_v_Germany_%282014_FIFA_World_Cup%29) during the 2014 World Cup.\n", "\n", "Below, `players` consists of two nested `dict` objects, one for each team, that hold `tuple` objects (i.e., records) with information on the players. Besides the jersey number, name, and position, each `tuple` objects contains a `list` object with the times when the player scored." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "players = {\n", " \"Brazil\": [\n", " (12, \"Júlio César\", \"Goalkeeper\", []),\n", " (4, \"David Luiz\", \"Defender\", []),\n", " (6, \"Marcelo\", \"Defender\", []),\n", " (13, \"Dante\", \"Defender\", []),\n", " (23, \"Maicon\", \"Defender\", []),\n", " (5, \"Fernandinho\", \"Midfielder\", []),\n", " (7, \"Hulk\", \"Midfielder\", []),\n", " (8, \"Paulinho\", \"Midfielder\", []),\n", " (11, \"Oscar\", \"Midfielder\", [90]),\n", " (16, \"Ramires\", \"Midfielder\", []),\n", " (17, \"Luiz Gustavo\", \"Midfielder\", []),\n", " (19, \"Willian\", \"Midfielder\", []),\n", " (9, \"Fred\", \"Striker\", []),\n", " ],\n", " \"Germany\": [\n", " (1, \"Manuel Neuer\", \"Goalkeeper\", []),\n", " (4, \"Benedikt Höwedes\", \"Defender\", []),\n", " (5, \"Mats Hummels\", \"Defender\", []),\n", " (16, \"Philipp Lahm\", \"Defender\", []),\n", " (17, \"Per Mertesacker\", \"Defender\", []),\n", " (20, \"Jérôme Boateng\", \"Defender\", []),\n", " (6, \"Sami Khedira\", \"Midfielder\", [29]),\n", " (7, \"Bastian Schweinsteiger\", \"Midfielder\", []),\n", " (8, \"Mesut Özil\", \"Midfielder\", []),\n", " (13, \"Thomas Müller\", \"Midfielder\", [11]),\n", " (14, \"Julian Draxler\", \"Midfielder\", []),\n", " (18, \"Toni Kroos\", \"Midfielder\", [24, 26]),\n", " (9, \"André Schürrle\", \"Striker\", [69, 79]),\n", " (11, \"Miroslav Klose\", \"Striker\", [23]),\n", " ],\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Q1.1**: Write a dictionary comprehension to derive a new `dict` object, called `brazilian_players`, that maps a Brazilian player's name to his position!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "brazilian_players = {...}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "brazilian_players" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Q1.2**: Generalize the code fragment into a `get_players()` function: Passed a `team` name, it returns a `dict` object like `brazilian_players`. Verify that the function works for the German team!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_players(team):\n", " ..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "get_players(\"Germany\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Often, we are given a `dict` object like the one returned from `get_players()`: It is characterized by the observation that a large set of unique keys (i.e., the players' names) is mapped onto a smaller set of non-unique values (i.e., the positions).\n", "\n", "**Q1.3**: Create a generic `invert()` function that swaps the keys and values of a `mapping` argument passed to it and returns them in a *new* `dict` object! Ensure that *no* key gets lost. Verify your implementation with the `brazilian_players` dictionary!\n", "\n", "Hints: Think of this as a grouping operation. The *new* values are `list` or `tuple` objects that hold the original keys. You may want to use either the the [defaultdict](https://docs.python.org/3/library/collections.html#collections.defaultdict) type from the [collections](https://docs.python.org/3/library/collections.html) module in the [standard library](https://docs.python.org/3/library/index.html) or the [setdefault()](https://docs.python.org/3/library/stdtypes.html#dict.setdefault) method of the ordinary `dict` type." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def invert(mapping):\n", " ..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "invert(brazilian_players)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Q1.4**: Write a `score_at_minute()` function: It takes two arguments, `team` and `minute`, and returns the number of goals the `team` has scored up until this time in the game.\n", "\n", "Hints: The function may reference the global `players` for simplicity. Earn bonus points if you can write this in a one-line expression using some *reduction* function and a *generator expression*." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def score_at_minute(team, minute):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The score at half time was:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "score_at_minute(\"Brazil\", 45)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "score_at_minute(\"Germany\", 45)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The final score was:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "score_at_minute(\"Brazil\", 90)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "score_at_minute(\"Germany\", 90)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Q1.5**: Write a `goals_by_player()` function: It takes an argument like the global `players`, and returns a `dict` object mapping the players to the number of goals they scored.\n", "\n", "Hints: Do *not* \"hard code\" the names of the teams! Earn bonus points if you can solve it in a single dictionary comprehension." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def goals_by_player(players):\n", " ..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "goals_by_player(players)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Q1.6**: Write a *dictionary comprehension* to filter out the players who did *not* score from the preceding result. Then, write a *set comprehension* that does the same but discards the number of goals scored.\n", "\n", "Hints: Reference the `goals_by_player()` function from before." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "{...}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "{...}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Q1.7**: Write a `all_goals()` function: It takes one argument like the global `players` and returns a `list` object containing $2$-element `tuple` objects, where the first element is the minute a player scored and the second his name. The list should be sorted by the time.\n", "\n", "Hints: You may want to use either the built-in [sorted()](https://docs.python.org/3/library/functions.html#sorted) function or the `list` type's [sort()](https://docs.python.org/3/library/stdtypes.html#list.sort) method. Earn bonus points if you can write a one-line expression with a *generator expression*." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def all_goals(players):\n", " ..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "all_goals(players)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Q1.8**: Lastly, write a `summary()` function: It takes one argument like the global `players` and prints out a concise report of the goals, the score at the half, and the final result.\n", "\n", "Hints: Use the `all_goals()` and `score_at_minute()` functions from before.\n", "\n", "The output should look similar to this:\n", "```\n", "12' Gerd Müller scores\n", "...\n", "HALFTIME: TeamA 1 TeamB 2\n", "77' Ronaldo scores\n", "...\n", "FINAL: TeamA 1 TeamB 3\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def summary(players):\n", " ..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "summary(players)" ] } ], "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.4" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": false, "sideBar": true, "skip_h1_title": true, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": false, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 4 }