{"id":"dictionaries-records","slug":"records","title":"Dictionaries as records","text":"A dictionary is a good way to keep the facts about one thing together, each under a name of its own:\n\n```python\nperson = {\"name\": \"Ada\", \"age\": 36, \"city\": \"London\"}\nprint(person[\"name\"], \"is\", person[\"age\"])\nperson[\"age\"] += 1\nprint(person)\n```\n\n```output\nAda is 36\n{'name': 'Ada', 'age': 37, 'city': 'London'}\n```\n\nCompare it with a list record, as earlier in this part: `[\"Ada\", 36, \"London\"]`. With the list, you have to remember that index 1 is the age. With the dictionary, the key says it: `person[\"age\"]`. A record can also get new facts later, `person[\"email\"] = \"ada@example.com\"`, without moving anything that's already in it. The keys are strings like any other, so spell them the same way every time: `person[\"Age\"]` would stop with a `KeyError`.\n\n### A list of records\n\nA list of such dictionaries, all with the same keys, is a small database:\n\n```python\nbooks = [\n    {\"title\": \"The Glass Garden\", \"author\": \"Mia Stone\", \"pages\": 312},\n    {\"title\": \"Night Trains\", \"author\": \"Leo Grant\", \"pages\": 205},\n    {\"title\": \"Paper Moons\", \"author\": \"Mia Stone\", \"pages\": 260},\n]\n\nfor book in books:\n    print(f\"{book['title']} by {book['author']}\")\n\ntotal = 0\nfor book in books:\n    total += book[\"pages\"]\nprint(\"Average length:\", total / len(books))\n```\n\n```output\nThe Glass Garden by Mia Stone\nNight Trains by Leo Grant\nPaper Moons by Mia Stone\nAverage length: 259.0\n```\n\nOn each round, `book` is one dictionary, and `book[\"title\"]` is its title. Inside an f-string that is itself in double quotes, write the key in single quotes, `book['title']`.\n\nFunctions make such a database easy to use. This one searches it and returns a new list of the matching titles:\n\n```python\ndef short_books(books: list, max_pages: int) -> list:\n    titles = []\n    for book in books:\n        if book[\"pages\"] <= max_pages:\n            titles.append(book[\"title\"])\n    return titles\n\n\nbooks = [\n    {\"title\": \"The Glass Garden\", \"author\": \"Mia Stone\", \"pages\": 312},\n    {\"title\": \"Night Trains\", \"author\": \"Leo Grant\", \"pages\": 205},\n    {\"title\": \"Paper Moons\", \"author\": \"Mia Stone\", \"pages\": 260},\n]\nprint(short_books(books, 300))\n```\n\n```output\n['Night Trains', 'Paper Moons']\n```\n","task":"Fill in the blanks so the function `make_book(title, author, year)` returns a book record with the keys `\"title\"`, `\"author\"` and `\"year\"`. For example, `make_book(\"Night Trains\", \"Leo Grant\", 1998)` returns `{'title': 'Night Trains', 'author': 'Leo Grant', 'year': 1998}`.\n","kind":"fill","seed":"def make_book(title: str, author: str, year: int) -> dict:\n    book = [[{}]]\n    book[\"title\"] = title\n    book[[[\"author\"‖'author']]] = author\n    book[\"year\"] = [[year]]\n    return book\n\n\nif __name__ == \"__main__\":\n    print(make_book(\"Night Trains\", \"Leo Grant\", 1998))\n","solution":"def make_book(title: str, author: str, year: int) -> dict:\n    book = {}\n    book[\"title\"] = title\n    book[\"author\"] = author\n    book[\"year\"] = year\n    return book\n\n\nif __name__ == \"__main__\":\n    print(make_book(\"Night Trains\", \"Leo Grant\", 1998))\n","hints":["The record starts as an empty dictionary, and each line after that adds one key.","An empty dictionary is `{}`. The second blank is the key `\"author\"`, in quotes, and the third is the parameter that holds the year."],"tests":[{"name":"make_book(\"Night Trains\", \"Leo Grant\", 1998)","stdin":"","call":"make_book(\"Night Trains\", \"Leo Grant\", 1998)\n","expect":"{'title': 'Night Trains', 'author': 'Leo Grant', 'year': 1998}","hidden":false,"returns":true},{"name":"make_book(\"Paper Moons\", \"Mia Stone\", 1987)","stdin":"","call":"make_book(\"Paper Moons\", \"Mia Stone\", 1987)\n","expect":"{'title': 'Paper Moons', 'author': 'Mia Stone', 'year': 1987}","hidden":true,"returns":true}],"require":[],"forbid":[],"more":[{"task":"Each book is a dictionary with the keys `\"title\"`, `\"author\"` and `\"year\"`. Write a function `oldest_title(books)` that returns the title of the oldest book in the list. There is always at least one book, and no two books have the same year.\n\nFor example, for the books `[{\"title\": \"Night Trains\", \"author\": \"Leo Grant\", \"year\": 1998}, {\"title\": \"Paper Moons\", \"author\": \"Mia Stone\", \"year\": 1987}]`, it returns `\"Paper Moons\"`.\n","kind":"code","seed":"def oldest_title(books: list) -> str:\n    pass\n\n\nif __name__ == \"__main__\":\n    books = [\n        {\"title\": \"Night Trains\", \"author\": \"Leo Grant\", \"year\": 1998},\n        {\"title\": \"Paper Moons\", \"author\": \"Mia Stone\", \"year\": 1987},\n    ]\n    print(oldest_title(books))\n","solution":"def oldest_title(books: list) -> str:\n    oldest = books[0]\n    for book in books:\n        if book[\"year\"] < oldest[\"year\"]:\n            oldest = book\n    return oldest[\"title\"]\n\n\nif __name__ == \"__main__\":\n    books = [\n        {\"title\": \"Night Trains\", \"author\": \"Leo Grant\", \"year\": 1998},\n        {\"title\": \"Paper Moons\", \"author\": \"Mia Stone\", \"year\": 1987},\n    ]\n    print(oldest_title(books))\n","hints":["Keep the oldest book so far in a variable, starting with the first one: `oldest = books[0]`.","Go through the books, and when a book's `\"year\"` is smaller than the oldest one's, it becomes the oldest.","Return only the title: `oldest[\"title\"]`."],"tests":[{"name":"Test 1","stdin":"","call":"books = [\n    {\"title\": \"Night Trains\", \"author\": \"Leo Grant\", \"year\": 1998},\n    {\"title\": \"Paper Moons\", \"author\": \"Mia Stone\", \"year\": 1987},\n]\nprint(oldest_title(books))\n","expect":"Paper Moons","hidden":false},{"name":"Test 2","stdin":"","call":"books = [\n    {\"title\": \"Paper Moons\", \"author\": \"Mia Stone\", \"year\": 1987},\n    {\"title\": \"The Glass Garden\", \"author\": \"Mia Stone\", \"year\": 2011},\n    {\"title\": \"Salt Roads\", \"author\": \"Ana Ruiz\", \"year\": 1979},\n]\nprint(oldest_title(books))\n","expect":"Salt Roads","hidden":true},{"name":"Test 3","stdin":"","call":"books = [\n    {\"title\": \"River Lights\", \"author\": \"Ana Ruiz\", \"year\": 1990},\n    {\"title\": \"Old Maps\", \"author\": \"Leo Grant\", \"year\": 1950},\n    {\"title\": \"Winter Bells\", \"author\": \"Bo Lind\", \"year\": 1970},\n]\nprint(oldest_title(books))\n","expect":"Old Maps","hidden":true},{"name":"oldest_title([{\"title\": \"Alone\", \"author\": \"Bo Lind\", \"year\": 2020}])","stdin":"","call":"oldest_title([{\"title\": \"Alone\", \"author\": \"Bo Lind\", \"year\": 2020}])\n","expect":"'Alone'","hidden":true,"returns":true}],"require":[],"forbid":[]},{"task":"Each book is a dictionary with the keys `\"title\"`, `\"author\"` and `\"year\"`. Write a function `count_by_author(books)` that returns a dictionary in which each author is a key and the value is the number of their books in the list.\n\n```python\nbooks = [\n    {\"title\": \"The Glass Garden\", \"author\": \"Mia Stone\", \"year\": 2011},\n    {\"title\": \"Night Trains\", \"author\": \"Leo Grant\", \"year\": 1998},\n    {\"title\": \"Paper Moons\", \"author\": \"Mia Stone\", \"year\": 1987},\n]\nprint(count_by_author(books))\n```\n\n```\n{'Mia Stone': 2, 'Leo Grant': 1}\n```\n","kind":"code","seed":"def count_by_author(books: list) -> dict:\n    pass\n\n\nif __name__ == \"__main__\":\n    books = [\n        {\"title\": \"The Glass Garden\", \"author\": \"Mia Stone\", \"year\": 2011},\n        {\"title\": \"Night Trains\", \"author\": \"Leo Grant\", \"year\": 1998},\n        {\"title\": \"Paper Moons\", \"author\": \"Mia Stone\", \"year\": 1987},\n    ]\n    print(count_by_author(books))\n","solution":"def count_by_author(books: list) -> dict:\n    counts = {}\n    for book in books:\n        author = book[\"author\"]\n        if author not in counts:\n            counts[author] = 0\n        counts[author] += 1\n    return counts\n\n\nif __name__ == \"__main__\":\n    books = [\n        {\"title\": \"The Glass Garden\", \"author\": \"Mia Stone\", \"year\": 2011},\n        {\"title\": \"Night Trains\", \"author\": \"Leo Grant\", \"year\": 1998},\n        {\"title\": \"Paper Moons\", \"author\": \"Mia Stone\", \"year\": 1987},\n    ]\n    print(count_by_author(books))\n","hints":["This is the counting pattern of the previous step. What you count is each book's `book[\"author\"]`.","If the author isn't a key yet, give them the value 0. Then add one."],"tests":[{"name":"Test 1","stdin":"","call":"books = [\n    {\"title\": \"The Glass Garden\", \"author\": \"Mia Stone\", \"year\": 2011},\n    {\"title\": \"Night Trains\", \"author\": \"Leo Grant\", \"year\": 1998},\n    {\"title\": \"Paper Moons\", \"author\": \"Mia Stone\", \"year\": 1987},\n]\nprint(count_by_author(books))\n","expect":"{'Mia Stone': 2, 'Leo Grant': 1}","hidden":false},{"name":"Test 2","stdin":"","call":"books = [\n    {\"title\": \"Salt Roads\", \"author\": \"Ana Ruiz\", \"year\": 1979},\n    {\"title\": \"Blue Hour\", \"author\": \"Ana Ruiz\", \"year\": 1984},\n    {\"title\": \"Red Hour\", \"author\": \"Ana Ruiz\", \"year\": 1990},\n    {\"title\": \"Alone\", \"author\": \"Bo Lind\", \"year\": 2020},\n]\nprint(count_by_author(books))\n","expect":"{'Ana Ruiz': 3, 'Bo Lind': 1}","hidden":true},{"name":"count_by_author([])","stdin":"","call":"count_by_author([])\n","expect":"{}","hidden":true,"returns":true}],"require":[],"forbid":[]}]}