<jupyter_start><jupyter_text>ListsIn Python, we can build a **list** of individual data values.Here is the Python code to create a list of the five English vowels. Python lists are written inside square brackets with commas separating each element.```vowels = ['a', 'e', 'i', 'o', 'u']vowels```<jupyter_code>vowels = ['a', 'e', 'i', 'o', 'u']
print(vowels)<jupyter_output>['a', 'e', 'i', 'o', 'u']<jupyter_text>Conceptually, the elements of the list are numbered **starting with 0**. In the `vowels` list, the first entry, corresponding to the vowel "a", is numbered 0. Looking up an element of the list by number is called **indexing**.Here is the Python code to find the third entry in the list `vowels`, which has index 2.```vowels[2]```Below we index into the list of vowels to get the third entry, which has index 2.<jupyter_code>vowels[2]<jupyter_output><empty_output><jupyter_text>As a note, we can index into a string as well. Lists, strings, and many other individual Python data types are all **sequences** that share some common features.For instance, below we find the 3rd item in the string `'MCB200'`.<jupyter_code>'MCB200'[2]<jupyter_output><empty_output><jupyter_text>Another feature of lists, strings, and other sequences is the `len()` function. Thus, it can be used to find the length of a list, just as we used it to find the length of a string.Note that, since items are numbered starting from zero, the items in a list go from `0` through `len(...)-1` inclusive.<jupyter_code>print(len('MCB200'))
print(len(vowels))<jupyter_output>6
5<jupyter_text>Lists are **mutable**, in contrast to strings. For example, we can change one item in the list of vowels. To change an item in a list, assign a new value to it just as if it were a variable.To change an entry in a list, we can assign a value to the entry just as we assign a value to a variable. For example, here is the Python code to replace the entry for "i" with an upper-case "I".```vowels[2] = 'I'```<jupyter_code>vowels[2] = 'I'
print(vowels)

string = 'MCB200'
string[2] = 'b'<jupyter_output>['a', 'e', 'I', 'o', 'u']<jupyter_text>We can also change the list itself, by adding more items. The `append()` method puts a new item on the end of a list.The Python code to add a "y" to our list of vowels is```vowels.append('y')```<jupyter_code>vowels.append('y')
print(vowels)<jupyter_output>['a', 'e', 'I', 'o', 'u', 'y']<jupyter_text>A list can hold different types of items, including other lists!Below we create a list with an integer, a floating-point number, a string, and another list:<jupyter_code>stuff = [17, 3.14159, 'MCB200', ['bbbb', 'cccc', 'dddd']]
print(stuff)
print(stuff[3])
print(len(stuff))
print(len(stuff[3]))

print(stuff[3][1])

print(stuff[3][1][0])
x = [ 3,2,4,7,5]
print(x)
x.sort()
print(x)

y = [ 23, 2, 4.0, 7.0, 5]
y.sort()
y<jupyter_output>[3, 2, 4, 7, 5]
[2, 3, 4, 5, 7]<jupyter_text>Iteration (`for` loops)The `for` loop in Python allows us to repeat an action for each element of a list, in order. Within the `for` loop, there is a special **loop variable** that will hold the value of the list item.The **body** of the `for` loop is the block of Python executed once for each item in the list. The loop body is indented underneath the line starting the `for` loop. In the example below, we loop over each vowel in our list of vowels and print that vowel. We name the loop variable here `v`.```for v in vowels:    print(v)```<jupyter_code>for v in vowels:
    print(v)<jupyter_output>a
e
I
o
u
y<jupyter_text>Just as with indexing, we can loop over the characters in a string just like we loop over items in a list. Here we loop over each individual character in the string `'MCB200'` and print that character.<jupyter_code>for x in 'MCB200':
    print(x)<jupyter_output>M
C
B
2
0
0<jupyter_text>A `for` loop **iterates** over each item in a list or a string. We can iterate over sequences, and more generally, over the items in other kinds of **collections** that we'll learn about later. We can _nest_ one `for` loop inside another one. On each pass through the outer `for` loop, we'll run the entire inner `for` loop. The body of the inner `for` loop is indented _twice_ to indicate that it;s Here is Python code that uses two nested `for` loops to print every combination of two nucleotides.```for nt1 in ['A', 'C', 'G', 'T']:    for nt2 in ['A', 'C', 'G', 'T']:        print(nt1 + nt2)```<jupyter_code>for nt1 in ['A', 'C', 'G', 'T']:
    for nt2 in ['A', 'C', 'G', 'T']:
        print(nt1 + nt2)<jupyter_output>AA
AC
AG
AT
CA
CC
CG
CT
GA
GC
GG
GT
TA
TC
TG
TT<jupyter_text>We can use the `for` loop to do more than just print items from a list. For example, we can use a `for` loop to compute a running total of items in a list. To do this, we'll make a (non-loop) variable to hold the running sum and initialize it to zero. ```total = 0```Then, we'll iterate through the items in the list and add each item to this running sum. ```for i in [1,2,3,4,5,6,7,8,9,10]:    total = total + i    print(total)```<jupyter_code>total = 0
for i in [1,2,3,4,5,6,7,8,9,10]:
    print('i = ' + str(i))
    total = total + i
    print(total)<jupyter_output>i = 1
1
i = 2
3
i = 3
6
i = 4
10
i = 5
15
i = 6
21
i = 7
28
i = 8
36
i = 9
45
i = 10
55<jupyter_text>Recall that $ \sum\limits_{i=1}^{n} i = \frac{n \cdot (n+1)}{2}$ and so our final result $\frac{10\cdot11}{2} = 55$ is correct. The intermediate values $\frac{1\cdot2}{2} = 1, \frac{2\cdot3}{2} = 3, \cdots$ all check out too. _Exercise_ Re-work the `for` loop above to build a _string_ that holds each of the numbers in the list. Building a string looks a lot like computing a sum. Remember that `str()` converts a number into a string.<jupyter_code>total = ''
for i in [1,2,3,4,5,6,7,8,9,10]:
    print('i = ' + str(i))
    total = total + str(i) + ' '
    print(total)<jupyter_output>i = 1
1 
i = 2
1 2 
i = 3
1 2 3 
i = 4
1 2 3 4 
i = 5
1 2 3 4 5 
i = 6
1 2 3 4 5 6 
i = 7
1 2 3 4 5 6 7 
i = 8
1 2 3 4 5 6 7 8 
i = 9
1 2 3 4 5 6 7 8 9 
i = 10
1 2 3 4 5 6 7 8 9 10<jupyter_text>_Exercise_ Re-work the `for` loop above to _build a new list_ that has the _square_ of each number in the starting list. Building a list is just one step more complicated than building a string -- we learned above about `append()`_Note_ Although we didn't discuss it, we can also use `+` to add together two lists. Just keep in mind that `append()` adds an _item_ to a _list_, but `+` will add _two lists_ together.<jupyter_code>total = []
for i in [1,2,3,4,5,6,7,8,9,10]:
    print('i = ' + str(i))
    total.append(i*i)
    print(total)<jupyter_output>i = 1
[1]
i = 2
[1, 4]
i = 3
[1, 4, 9]
i = 4
[1, 4, 9, 16]
i = 5
[1, 4, 9, 16, 25]
i = 6
[1, 4, 9, 16, 25, 36]
i = 7
[1, 4, 9, 16, 25, 36, 49]
i = 8
[1, 4, 9, 16, 25, 36, 49, 64]
i = 9
[1, 4, 9, 16, 25, 36, 49, 64, 81]
i = 10
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
{'fraction_non_alphanumeric': 0.13174788444703822, 'fraction_numerical': 0.04946016924423694, 'mean_word_length': 4.089086859688196, 'pattern_counts': {'":': 0, '<': 42, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '99808', 'license': 'MIT', 'n_tokens_mistral': 2784, 'n_tokens_neox': 2496, 'n_words': 1108, 'path': '0828_intro/02_more_python_done.ipynb', 'repo_name': 'ingolia/mcb200-2020', 'size': '6854'}