{"assignment":{"_schema_version":2,"course_id":37,"date_created":"2022-06-28T19:00:00+00:00","date_modified":"2024-10-03T14:13:11.537293+00:00","extra_instructor_files":"","extra_starting_files":"","forked_id":null,"forked_version":null,"hidden":false,"id":1075,"instructions":"## Even More Loop Patterns\n\n- **Find:** Get the first/last element that matches a condition.\n- **Take:** Keep all the elements until they match a condition.\n- **Min/max:** Find the highest or lowest element in a list.\n\nWe've already seen the sum, count, accumulate, map, and filter patterns.\nNow, we're going to cover a few more patterns that incorporate conditionals.\nThese are the find, take, min, and max patterns.\n\n\n\n\n## The Find Pattern\n\n```python\nfound = None\nfor item in my_list:\n    if ___:\n        found = item\n```\n\nIn the example shown here, we have a list of items and want to find a specific value based on a condition.\nThis requires us to walk through the entire list and check whether that value satisfies our condition.\nWhen we are done, the desired value will be in the `found` variable, or found will have the value `None`.\nYou will need to replace the blank with an appropriate condition, and you will often want to replace the value `None` with a suitable default value.\n\n## Find Last Variant\n\n```python find-last-variant\nfrom bakery import assert_equal\n\ndef find_last_question(words: list[str]) -> str:\n    result = \"Missing\"\n    for word in words:\n        if word[-1] == \"?\":\n            result = word\n    return result\n\nsome_words = [\"Hi?\", \"Oh.\", \"Uh?\"]\nassert_equal(find_last_question(some_words), \"Uh?\")\n```\n\nThe find pattern comes in two variants.\nThe first version will find the last element in the list that matches the given condition.\nThe key idea is that the accumulation variable is manipulated repeatedly by the loop and only returned when the entire loop is finished.\nContrast that with the next variant of the find pattern, though.\n\n## Find First Variant\n\n```python find-last-variant\nfrom bakery import assert_equal\n\ndef find_first_question(words: list[str]) -> str:\n    for word in words:\n        if word[-1] == \"?\":\n            return word\n    return \"Missing\"\n\nsome_words = [\"Hi?\", \"Oh.\", \"Uh?\"]\nassert_equal(find_first_question(some_words), \"Hi?\")\n```\n\nIn the other variant of the find pattern, the program behaves differently.\nInstead of returning the last element that matches the given condition, the first element that is encountered is returned instead.\nThis variant relies on the control flow breaking behavior of the `return` statement to exit out of the `for` loop as soon as an element matches the condition.\nThe `return` statement, when encountered, immediately ends the `for` loop and the entire function regardless of anything else.\nThis is why it is critical to make sure that your `return` statements are always guarded by `if` statements.\nYou will pretty much never ever see a `return` statement directly inside of a `for` loop UNLESS there is an `if` statement wrapped around it.\n\n## The Take Pattern\n\n```python\ntaking = True\nnew_list = []\nfor item in my_list:\n    if ___:\n        taking = False\n    elif taking:\n        new_list.append(item)\n```\n\nThe take pattern is a cousin of the find and filter patterns but has significantly more complexity.\nIn the example shown here, we have a list of items, and we want a copy of the items up until a certain point.\nWe again must walk through the list, but this time we will continue adding new items up until we satisfy our condition.\nNotice that the body of the loop is more complicated, using an `elif` statement to prevent us from taking elements as soon as we have met the condition.\nWe should look at an example with more context.\n\n## The Take Pattern in Action\n\n```python take-pattern-example\nwords = [\"Oh\", \"Hi\", \"There!\", \"Okay\", \"Bye!\"]\ntaking = True\nfirst_words = []\nfor word in words:\n    if word[-1] == \"!\":\n        taking = False\n    elif taking:\n        first_words.append(word)\n\nprint(first_words)\n# ['Oh', 'Hi']\n```\n\nIn this example program, we use the take pattern to grab the first two elements of the list.\nHowever, it was not that we intentionally only chose the first two elements specifically.\nInstead, the logic of the pattern had us go through every element of the list until we encountered the first element that matched our condition.\nAfter that element, we stopped accumulating elements in our new list.\nAt the end, the fact that we only took the first two elements is a consequence of their data, not some arbitrary constant length.\n\n## The Min/Max Pattern\n\n```python max-pattern\nmaximum = a_list[0]\nfor item in a_list:\n    if item > maximum:\n        maximum = item\n\nprint(maximum)\n```\n\nThe last pattern is used to find the highest or lowest element in a list.\nThis pattern is like the find pattern.\nHowever, you will notice the conditional compares each value to the accumulated value.\nUsing this pattern, the accumulated value (in this case a maximum) will end up as the highest value in the list.\nThe corresponding minimum pattern works similarly, except the less than operator is used instead of the greater than operator.\n\n## Maximum of Non-Empty Lists\n\n```python non-empty-max\ndef highest(numbers: list[int]) -> int:\n    # Critical guard!\n    if not numbers:\n        return 0\n    # Pattern continues from here\n    maximum = numbers[0]\n    for number in numbers:\n        if number > maximum:\n            maximum = number\n    return maximum\n```\n\nA small but important detail often overlooked with the minimum and maximum patterns is that they require the list to be non-empty before you initialize the accumulation variable.\nRemember, you cannot index the first element of an empty list since there is no first element in an empty list.\nTherefore, most practical implementations of the pattern will begin by incorporating the guard pattern that we previously learned about in logical patterns.\n\n## Summary\n\n- There are several other loop patterns, all of which involve conditionals:\n  - Find: Get the first/last element that matches a condition.\n  - Take: Get all the elements until they match a condition.\n  - Min/max: Find the highest or lowest element in a list.\n- When the find pattern is used inside of a function and you are searching for the first element that matches the condition, you can return early from the function. But, if you are looking for the last element that matches the condition, you should not return early.\n- The min and max patterns are distinguished by the direction of the order comparison operator used.\n- Be careful to not use the min/max pattern on an empty list or it will cause an IndexError.\n\n","ip_ranges":"","name":"6B1) For Loop Patterns 2 Reading","on_change":"","on_eval":"","on_run":"","owner_id":1,"owner_id__email":"acbart@udel.edu","points":0,"public":true,"reviewed":false,"sample_submissions":[],"settings":"{\n  \"header\": \"More Loop Patterns\",\n  \"slides\": \"bakery_for_patterns2.pdf\",\n  \"youtube\": {\n    \"Bart\": \"r6JWfmmdMb8\",\n    \"Amy\": \"rNZP9cZ3ih8\"\n  },\n  \"sumary\": \"This lesson covers more loop patterns. These additional patterns involve more complex conditionals and state.\",\n  \"small_layout\": true,\n  \"video\": {\n    \"Bart\": \"https://blockpy.cis.udel.edu/videos/bakery_for_patterns2-Bart.mp4\",\n    \"Amy\": \"https://blockpy.cis.udel.edu/videos/bakery_for_patterns2-Amy.mp4\"\n  }\n}","starting_code":"","subordinate":true,"tags":[],"type":"reading","url":"bakery_for_patterns2_read","version":11},"ip":"216.73.216.157","submission":{"_schema_version":3,"assignment_id":1075,"assignment_version":11,"attempts":0,"code":"","correct":false,"course_id":37,"date_created":"2026-05-20T23:50:33.015926+00:00","date_due":"","date_graded":"","date_locked":"","date_modified":"2026-05-20T23:50:33.015926+00:00","date_started":"","date_submitted":"","endpoint":"","extra_files":"","feedback":"","grading_status":"NotReady","id":2037089,"score":0.0,"submission_status":"Started","time_limit":"","url":"submission_url-cd1b4f52-ed06-47d1-877c-b6af1bb23f59","user_id":2044772,"user_id__email":"","version":0},"success":true}
