{"id":"more-comprehensions-dictionaries","slug":"dictionaries","title":"Dictionary comprehensions","text":"In part 5 you built dictionaries with a loop: start from an empty dictionary, and in each round store a value under a key. This one turns temperatures in Celsius into Fahrenheit:\n\n```python\ncelsius = [0, 25, 100]\nfahrenheit = {}\nfor c in celsius:\n    fahrenheit[c] = c * 9 / 5 + 32\nprint(fahrenheit)\n```\n\n```output\n{0: 32.0, 25: 77.0, 100: 212.0}\n```\n\nA **dictionary comprehension** says the same in one line. It's written in curly brackets, like a dictionary, and in front of the `for` it has a key and a value with a colon between them, like a pair in a dictionary:\n\n```python\ncelsius = [0, 25, 100]\nfahrenheit = {c: c * 9 / 5 + 32 for c in celsius}\nprint(fahrenheit)\n```\n\n```output\n{0: 32.0, 25: 77.0, 100: 212.0}\n```\n\nThe shape is:\n\n```text\n{key: value for item in series}\n```\n\nCompare it with the loop: what comes before the colon, `c`, is what went between the square brackets in `fahrenheit[c]`, and what comes after it is the value that was stored there. A filter with `if` at the end works just as in a list comprehension.\n\n### A key only once\n\nA dictionary has each key only once. When a comprehension makes the same key again, the new value replaces the old one, and the key keeps its place from the first time. Here every fruit goes under its first letter:\n\n```python\nfruits = [\"apple\", \"avocado\", \"banana\", \"blueberry\", \"cherry\"]\nby_letter = {fruit[0]: fruit for fruit in fruits}\nprint(by_letter)\n```\n\n```output\n{'a': 'avocado', 'b': 'blueberry', 'c': 'cherry'}\n```\n\n`\"apple\"` went in first, under `\"a\"`, and then `\"avocado\"` took its place. Five fruits went in, but the dictionary has only three keys, and for each letter the last fruit wins.\n\n### From a dictionary to a dictionary\n\nTo go through a dictionary's keys and values together, use its `items()` method, as in a `for` loop. Then the new dictionary can change the values, leave some pairs out, or even swap the keys and values:\n\n```pycon\n>>> prices = {\"tea\": 3, \"cake\": 5, \"soup\": 8}\n>>> {name: price * 2 for name, price in prices.items()}\n{'tea': 6, 'cake': 10, 'soup': 16}\n>>> {name: price for name, price in prices.items() if price < 6}\n{'tea': 3, 'cake': 5}\n>>> {price: name for name, price in prices.items()}\n{3: 'tea', 5: 'cake', 8: 'soup'}\n```\n\nTwo lists of the same length can become one dictionary, with the indexes from `range(len(...))`:\n\n```python\nnames = [\"Ada\", \"Alan\", \"Grace\"]\nborn = [1815, 1912, 1906]\nyears = {names[i]: born[i] for i in range(len(names))}\nprint(years)\n```\n\n```output\n{'Ada': 1815, 'Alan': 1912, 'Grace': 1906}\n```\n\n### Curly brackets, not square ones\n\nA key and a value with a colon only work inside curly brackets. In square brackets, Python stops at the colon:\n\n```python\ncelsius = [0, 25, 100]\nfahrenheit = [c: c * 9 / 5 + 32 for c in celsius]\n```\n\n```crash\n  File \"main.py\", line 2\n    fahrenheit = [c: c * 9 / 5 + 32 for c in celsius]\n                   ^\nSyntaxError: invalid syntax\n```\n","task":"Fill in the blank so that the dictionary has the numbers 1 to 5 as its keys and each number's square as its value. The program should print:\n\n```\n{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}\n```\n","kind":"fill","seed":"squares = {n: [[n * n‖n ** 2]] for n in range(1, 6)}\nprint(squares)\n","solution":"squares = {n: n * n for n in range(1, 6)}\nprint(squares)\n","hints":["The key comes before the colon and the value after it. The key is the number `n` itself.","The value is the square of `n`: `n * n`."],"tests":[{"name":"Output","stdin":"","expect":"{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}","hidden":false}],"require":[],"forbid":[],"more":[{"task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"words = [\"sun\", \"moon\", \"star\", \"sky\"]\nby_length = {len(w): w for w in words}\nprint(by_length)\nprint(len(by_length))\nprint({w: n for n, w in by_length.items()})\n","solution":"words = [\"sun\", \"moon\", \"star\", \"sky\"]\nby_length = {len(w): w for w in words}\nprint(by_length)\nprint(len(by_length))\nprint({w: n for n, w in by_length.items()})\n","hints":["The key is the length of each word. Two of the words have 3 letters, and two have 4.","When a key comes again, its new value replaces the old one, but the key stays where it was first put. `len` of a dictionary is the number of its keys.","The last comprehension goes through the pairs that `items()` gives and swaps each key and value."],"tests":[{"name":"Output","stdin":"","expect":"{3: 'sky', 4: 'star'}\n2\n{'sky': 3, 'star': 4}","hidden":false}],"require":[],"forbid":[],"lines":["{3: 'sky', 4: 'star'}","2","{'sky': 3, 'star': 4}"]},{"task":"Write a function `passed(scores, limit)` that gets a dictionary of names and scores, and returns a new dictionary with only the people whose score is at least `limit`. Use a dictionary comprehension.\n\nFor example, this call:\n\n```python\nprint(passed({\"Ann\": 72, \"Bo\": 45, \"Cy\": 90}, 50))\n```\n\nprints:\n\n```\n{'Ann': 72, 'Cy': 90}\n```\n","kind":"code","seed":"def passed(scores, limit):\n    pass\n\n\nif __name__ == \"__main__\":\n    print(passed({\"Ann\": 72, \"Bo\": 45, \"Cy\": 90}, 50))\n","solution":"def passed(scores, limit):\n    return {name: score for name, score in scores.items() if score >= limit}\n\n\nif __name__ == \"__main__\":\n    print(passed({\"Ann\": 72, \"Bo\": 45, \"Cy\": 90}, 50))\n","hints":["Go through the names and scores together: `for name, score in scores.items()`.","The pairs stay as they are, so the key and value are `name: score`. A filter at the end leaves out the rest.","The filter is `if score >= limit`."],"tests":[{"name":"print(passed({\"Ann\": 72, \"Bo\": 45, \"Cy\": 90}, 50))","stdin":"","call":"print(passed({\"Ann\": 72, \"Bo\": 45, \"Cy\": 90}, 50))\n","expect":"{'Ann': 72, 'Cy': 90}","hidden":false},{"name":"passed({\"Dee\": 10, \"Eli\": 20, \"Fay\": 30}, 20)","stdin":"","call":"passed({\"Dee\": 10, \"Eli\": 20, \"Fay\": 30}, 20)\n","expect":"{'Eli': 20, 'Fay': 30}","hidden":true,"returns":true},{"name":"passed({\"Gus\": 1}, 5)","stdin":"","call":"passed({\"Gus\": 1}, 5)\n","expect":"{}","hidden":true,"returns":true}],"require":[{"pattern":"\\{[^\\n]*\\bfor\\b","message":"Build the new dictionary with a dictionary comprehension."}],"forbid":[]}]}