{"id":"dictionaries-looping","slug":"looping","title":"Going through a dictionary","text":"A `for` loop over a dictionary goes through its keys, in the order they were added. Each key gives you its value:\n\n```python\nstock = {\"apples\": 5, \"pears\": 0, \"plums\": 7}\nfor fruit in stock:\n    print(fruit, stock[fruit])\n```\n\n```output\napples 5\npears 0\nplums 7\n```\n\nWhen you need both the key and the value, the method `items()` gives them in pairs. The loop then has two variables, separated by a comma: the first one gets the key and the second one the value.\n\n```python\nstock = {\"apples\": 5, \"pears\": 0, \"plums\": 7}\nfor fruit, amount in stock.items():\n    if amount == 0:\n        print(f\"{fruit}: sold out\")\n    else:\n        print(f\"{fruit}: {amount} left\")\n```\n\n```output\napples: 5 left\npears: sold out\nplums: 7 left\n```\n\nHow one pair can fill two variables is explained in the tuples module at the end of this part.\n\nA loop may change the values of keys that are already there. Adding or removing keys during the loop is another matter, which the step on removing keys comes back to.\n\n```python\nstock = {\"apples\": 5, \"pears\": 0, \"plums\": 7}\nfor fruit in stock:\n    stock[fruit] += 10\nprint(stock)\n```\n\n```output\n{'apples': 15, 'pears': 10, 'plums': 17}\n```\n\n### In alphabetical order\n\n`sorted` works on a dictionary too: it returns a list of its keys, in order. Looping over that list goes through the dictionary in alphabetical order:\n\n```python\nphone_book = {\"Max\": \"555-0199\", \"Ada\": \"555-0123\", \"Lin\": \"555-0150\"}\nprint(sorted(phone_book))\nfor name in sorted(phone_book):\n    print(name, phone_book[name])\n```\n\n```output\n['Ada', 'Lin', 'Max']\nAda 555-0123\nLin 555-0150\nMax 555-0199\n```\n\n### The best pair\n\nFinding the largest value works as it does with a list, except that you usually want to remember the key that goes with it:\n\n```python\nvotes = {\"pizza\": 12, \"tacos\": 17, \"sushi\": 9}\n\nwinner = \"\"\nmost = 0\nfor food, count in votes.items():\n    if count > most:\n        winner = food\n        most = count\n\nprint(f\"{winner} won with {most} votes\")\n```\n\n```output\ntacos won with 17 votes\n```\n","task":"Fill in the blanks so the program prints each name with as many stars as the grade:\n\n```\nAda *****\nMax ***\nLin ****\n```\n","kind":"fill","seed":"grades = {\"Ada\": 5, \"Max\": 3, \"Lin\": 4}\nfor name, grade in grades.[[items]]():\n    stars = \"*\" * [[grade]]\n    print([[name]], stars)\n","solution":"grades = {\"Ada\": 5, \"Max\": 3, \"Lin\": 4}\nfor name, grade in grades.items():\n    stars = \"*\" * grade\n    print(name, stars)\n","hints":["The method that gives both the key and the value of each pair is `items()`.","On each round, `name` is the key and `grade` the value. `\"*\" * grade` repeats the star `grade` times."],"tests":[{"name":"Output","stdin":"","expect":"Ada *****\nMax ***\nLin ****","hidden":false}],"require":[],"forbid":[],"more":[{"task":"Write a function `best_student(grades)` that takes a dictionary of names and grades and returns the name with the highest grade. If several students share the highest grade, it returns the one that comes first in the dictionary. Grades are whole numbers from 1 to 5.\n\nFor example, `best_student({\"Ada\": 4, \"Max\": 3, \"Lin\": 5})` returns `\"Lin\"`.\n","kind":"code","seed":"def best_student(grades: dict) -> str:\n    pass\n\n\nif __name__ == \"__main__\":\n    print(best_student({\"Ada\": 4, \"Max\": 3, \"Lin\": 5}))\n","solution":"def best_student(grades: dict) -> str:\n    best = \"\"\n    highest = 0\n    for name, grade in grades.items():\n        if grade > highest:\n            best = name\n            highest = grade\n    return best\n\n\nif __name__ == \"__main__\":\n    print(best_student({\"Ada\": 4, \"Max\": 3, \"Lin\": 5}))\n","hints":["Keep two helper variables, the best name so far and its grade, and go through the pairs with `items()`.","When a grade is greater than the best so far, remember both the name and the grade.","Use `>`, not `>=`: then a later student with the same grade doesn't replace the first one."],"tests":[{"name":"best_student({\"Ada\": 4, \"Max\": 3, \"Lin\": 5})","stdin":"","call":"best_student({\"Ada\": 4, \"Max\": 3, \"Lin\": 5})\n","expect":"'Lin'","hidden":false,"returns":true},{"name":"best_student({\"Ada\": 5, \"Max\": 3, \"Lin\": 4})","stdin":"","call":"best_student({\"Ada\": 5, \"Max\": 3, \"Lin\": 4})\n","expect":"'Ada'","hidden":true,"returns":true},{"name":"best_student({\"Kim\": 1})","stdin":"","call":"best_student({\"Kim\": 1})\n","expect":"'Kim'","hidden":true,"returns":true},{"name":"best_student({\"Ana\": 4, \"Ben\": 5, \"Cid\": 5})","stdin":"","call":"best_student({\"Ana\": 4, \"Ben\": 5, \"Cid\": 5})\n","expect":"'Ben'","hidden":true,"returns":true}],"require":[],"forbid":[]},{"task":"A shop keeps its stock in a dictionary of products and amounts. Write a function `running_low(stock, limit)` that returns a list of the products whose amount is less than `limit`, in alphabetical order.\n\nFor example, `running_low({\"pens\": 3, \"clips\": 50, \"tape\": 1}, 5)` returns `['pens', 'tape']`.\n","kind":"code","seed":"def running_low(stock: dict, limit: int) -> list:\n    pass\n\n\nif __name__ == \"__main__\":\n    print(running_low({\"pens\": 3, \"clips\": 50, \"tape\": 1}, 5))\n","solution":"def running_low(stock: dict, limit: int) -> list:\n    low = []\n    for product in sorted(stock):\n        if stock[product] < limit:\n            low.append(product)\n    return low\n\n\nif __name__ == \"__main__\":\n    print(running_low({\"pens\": 3, \"clips\": 50, \"tape\": 1}, 5))\n","hints":["Go through the products, check each amount against `limit`, and append the low ones to a new list.","Loop over `sorted(stock)` to get the products in alphabetical order, or sort the result list before you return it."],"tests":[{"name":"running_low({\"pens\": 3, \"clips\": 50, \"tape\": 1}, 5)","stdin":"","call":"running_low({\"pens\": 3, \"clips\": 50, \"tape\": 1}, 5)\n","expect":"['pens', 'tape']","hidden":false,"returns":true},{"name":"running_low({\"zips\": 0, \"glue\": 2, \"ink\": 9}, 10)","stdin":"","call":"running_low({\"zips\": 0, \"glue\": 2, \"ink\": 9}, 10)\n","expect":"['glue', 'ink', 'zips']","hidden":true,"returns":true},{"name":"running_low({\"paper\": 100}, 100)","stdin":"","call":"running_low({\"paper\": 100}, 100)\n","expect":"[]","hidden":true,"returns":true}],"require":[],"forbid":[]}]}