<jupyter_start><jupyter_text>**Review of programming concepets*** calculations (7 * 3)* variables (result = 7 * 3)* lists [7, 3, 4, 5]* dicts* loops (for n in range(0, len(arrayname)))* conditionals* methods  ** Review of lists**We can create a list throught the [ ] syntaxIf we need multiple lists, we can create each one individually, though this can become inefficient<jupyter_code>week_1 = [55, 58, 52, 55, 58, 69, 70]
week_2 = [45, 52, 66, 62, 60, 58, 55]
week_3 = [50, 52, 52, 56, 50, 48, 47]
week_3<jupyter_output><empty_output><jupyter_text>In day 1, as an exercise, we wrote a method to find the max and min value in a list.  Python has a built in method to find this value for a list as well.We can use these methods together to caculate the range of temperature readings during a week<jupyter_code>min(week_1)
temp_range = max(week_1) - min(week_1)
print(temp_range)<jupyter_output>18<jupyter_text>**Methods**Suppose we wanted to encapsulate this method so we could reuse it throughout our code and notebook.We can do this with a method.<jupyter_code>def temperature_range(readings):
    temp_range = max(readings) - min(readings)
    return temp_range
temperature_range(week_1)<jupyter_output><empty_output><jupyter_text>Note this is identical to our use of built in methods in python.  We call temperature_range through the same syntax as a built in python method (for example, the max method).  We call the values within the ( ) the parameters.  Here, we pass two values to the max method, 1 and 2.<jupyter_code>max(1, 2)<jupyter_output><empty_output><jupyter_text>Let's try an easier example.  We can write a method to add two numbers.  Here, we create a method named add_two, and we pass it two values.  The return value is returned by the method as a parameter.  You can assign this value to a new variable.<jupyter_code>def add_two(first, second):
    return(first + second)
new_number = add_two(1, 2)
print(new_number)<jupyter_output>3<jupyter_text>**Exercise**use the temperature_range method to get the range for week 1, week 2, and week 3<jupyter_code>week_1
print(temperature_range(week_1))
print(temperature_range(week_2))
print(temperature_range(week_3))<jupyter_output>18
21
9<jupyter_text>The method is more efficient than re-doing the calculation for each week.  However, we are still calling the method three times, once for each list.  To make this more efficient and easier to maintain, with less typing (and fewer opportunities for resulting errors), let's create a **list of lists**. We'll start with a simpler example, adding two numbers.<jupyter_code>add_two(1, 2)<jupyter_output><empty_output><jupyter_text>We create three lists, each contains two values, and a method to add them together.<jupyter_code>val_1 = [1, 2]
val_2 = [2, 3]
val_3 = [3, 4]
def add_two(val_array):
    return(val_array[0] + val_array[1])
add_two(val_1)<jupyter_output><empty_output><jupyter_text>Previously, we created lists of primitive values (integers, strings, floats).  But we can just as easily create lists of lists<jupyter_code>all_vals = [val_1, val_2, val_3]<jupyter_output><empty_output><jupyter_text>The first value in a list of lists is... a list!<jupyter_code>all_vals[0]<jupyter_output><empty_output><jupyter_text>You can get the first value of the first through a series of brackets ([ ]).<jupyter_code>all_vals[0][0]<jupyter_output><empty_output><jupyter_text>Now that we have a list of lists, we can loop through each one, and print the resulting value<jupyter_code>for av in all_vals:
    print(av, add_two(av))<jupyter_output>[1, 2] 3
[2, 3] 5
[3, 4] 7<jupyter_text>**Exercise**Using the list of lists approach above, print the temp range for each week using the list of lists approach* create a list of lists composed of each week* use the add_two example to print the range<jupyter_code>temp_weeks = [week_1, week_2, week_3]
temp_weeks
for tw in temp_weeks:
    print(tw, temperature_range(tw))
for tw in temp_weeks:
    print(tw, temperature_range)<jupyter_output>[55, 58, 52, 55, 58, 69, 70] <function temperature_range at 0x104faf730>
[45, 52, 66, 62, 60, 58, 55] <function temperature_range at 0x104faf730>
[50, 52, 52, 56, 50, 48, 47] <function temperature_range at 0x104faf730><jupyter_text>**Dictionaries**You've seen lists, which allow you to store a series of values in order.  There's another very useful data structure you'll often encounter, called a **dictionary**.Think of a dictionary as a look up table.  A **key** is what you use to look up a **value**.<jupyter_code># dictionaries
locations = {"desert": 88, "mountain": 65, "coastal": 63}<jupyter_output><empty_output><jupyter_text>You could try this with parallel lists - but now you need to know the position of both values.<jupyter_code>temp_readings = [88, 65, 63]
temp_locations = ["desert", "mountain", "coastal"]<jupyter_output><empty_output><jupyter_text>With a dict, you can look up the temperature based on a **key**<jupyter_code>locations["coastal"]
locations.keys()
locations<jupyter_output><empty_output><jupyter_text>A question came up in class - what if there are multiple temperature readings for a key.  Just as you can store a list within a list, you can store a list within a dictionary (and vice-versa)<jupyter_code>locations = {"desert": 88, "mountain": 65, "coastal": [63, 61, 67]}
locations["coastal"]<jupyter_output><empty_output><jupyter_text>Or, alternatively, you can store another dictionary within a dictionary, which preserves the look up approach.<jupyter_code>locations = {"desert": 88, "mountain": 65, "coastal": {"low": 63, "high": 67}}
locations["coastal"]["high"]
low_high = locations["coastal"]
low_high["high"]
type(low_high)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1004566210045662, 'fraction_numerical': 0.036178433438707414, 'mean_word_length': 6.100997506234414, 'pattern_counts': {'":': 11, '<': 71, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '264470', 'license': 'MIT', 'n_tokens_mistral': 2041, 'n_tokens_neox': 1841, 'n_words': 690, 'path': 'swc-ucsf-python-12-01-2017-notes/pythonday2.ipynb', 'repo_name': 'ucsf-ckm/DataAnalytics', 'size': '5694'}