Lists and Loops

Learning Goals

After this week, the student will be able to:

  • Write programs using lists

  • Write programs using for-loops

  • Access and manipulate relevant features of strings

Lists

Lists are used for storing many variables in a compact way. You make one using brackets.

mylist = [10, "Stephen", 40, 99, False, "Fry"]
print(mylist)
[10, 'Stephen', 40, 99, False, 'Fry']

You can access specific elements in a list by writing the name of the list next to brackets with an index inside them.

print(mylist[0])
10

The first element in a list has the index 0, the second element has the index 1 and so on.

words = ["first", "second", "third", "fourth", "fifth", "sixth"]
print(words[0])
print(words[2])
print(words[1:5:2]) # Extra: Slicing! This gives elements from start:stop:step. In this case the elements with index 1 and 3.
first
third
['second', 'fourth', 'sixth']

While a variable can be though of like an address in computer memory with a specific value, a list is more like a parking lot. The list also has an address, but to get or store a value you need to specify a parking spot.

You can add elements to the end of a list by using the method .append(). Methods are like functions, only they need to be used on something. The .append() method for instance, needs to be used on a list.

words.append("fifth")
words.append(30)
print(words)
['first', 'second', 'third', 'fourth', 'fifth', 30]

You can change the elements of a list by using indexes.

words[1] = "something else"
print(words)
['first', 'something else', 'third', 'fourth', 'fifth', 30]

You can find the length of a list by using the function len().

print(len(words))
6

The in keyword checks if a value appears in a list and returns True or False.

if "third" in words:
    print("The string exists in the list")
The string exists in the list

In-Class Lists exercises

a) Create a list filled with the names of your favorite movies and shows.

  • Use .append() to add an element to it.

  • Print the second element of the list

  • Change the second element of the list to “Better Call Saul”

  • Print the second element of the list

  • Print the length of your list


Using Strings like lists

Last week, you learned how to define, add and print strings.

short = "Sam"
missing = "wise"
last = "Gamgee"
print(f"{short + missing} {last} is the best hobbit")
Samwise Gamgee is the best hobbit

But since working with text is so important, we will need some more tools.

Accessing characters in a string like a list

We define a string s

s = "Today is a fine day"
print(s)
Today is a fine day

Like a list, we can find its length using len()

length = len(s)
print(length)
19

And like a list we can use square brackets and indexes to access specific characters in a string.

print(s[0]) # First element has index 0
print(s[length - 1]) # the string has 19 elements, so the element has index 18!
print(s[-1]) # negative indexes work just like for lists
T
y
y

If we are interested in a part of the string, we can use slicing to isolate these letters.

sliced = s[2:14] # start:stop (not including stop index)
print(sliced)
day is a fin

Note that you cannot change a string like you would a list! Strings are strings, not lists.

print(type(s)) # not a list!
<class 'str'>
s[0] = "t"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-16-0638940c906a> in <module>
----> 1 s[0] = "t"

TypeError: 'str' object does not support item assignment
s.append(", just like yesterday")
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-17-3968ff7cb744> in <module>
----> 1 s.append(", just like yesterday")

AttributeError: 'str' object has no attribute 'append'

Strings are immutable objects, meaning that one cannot change its elements by indexing, as we can with lists.

Searching a String

If you want to pick out the position of a particular character or combination of characters in a string, you can use the built-in Python function find. This function returns the first index where the given combination of characters appear.

s.find("fine")
11
s.find("y")
4

If you want to find the last index where the given combination of characters appears, you can use the function rfind instead.

s.rfind("y")
18

If we try to find the word "sell", which does not occur in the string given, the function returns -1, indicating that the word does not exist in the string.

s.find("sell")
-1

Another function that basically does the same as find on strings is the function index. The only difference is that this function returns an error message instead of -1 if the word does not occur in the string. Similarily, the function rindex serves the same purpose as the function rfind, returning the last index of the given string.

If we want to know if a substring is a part of a string, but we do not need its location, we can also use the keyword in, as shown in the following.

"day" in s
True
"dark" in s
False

This can be usful for if statements.

if "fine" in s:
    print("fine was found")
else:
    print("fine was not found")
fine was found

For loops

One of the biggest strengths of computers is their ability to do many small operations over and over. Complex operations like performing statistical analysis, translating millions of sentences and simulating the spread of a disease cannot be done in one fell swoop, they must be broken into smaller parts which together give the correct result.

The simplest way of performing many small operations with code is using loops. Loops are used to run code over and over again. In Python there are two types of loops, while-loops and for-loops. We will focus on using for-loops, since they are more useful for our purposes.

If we wish to print “Hello World!” three times it can be done like this:

for i in range(3):
    print("Hello World!")
Hello World!
Hello World!
Hello World!

i is the iteration variable. It can be used inside the loop.

for i in range(3):
    print(f"The iteration variable has the value {i}")
The iteration variable has the value 0
The iteration variable has the value 1
The iteration variable has the value 2

The range() function determines how many times the for loop is run, and which values the iteration variable i will have for each iteration. range(3) makes the code inside the loop run once for each of the i values 0 -> 1 -> 2. range(100) would make the code inside the loop run once for each of the values 0 -> 1 -> … -> 98 -> 99 (100 times in total).

The range() function can also be used in a slightly different way. You can give it a number to start from, a number where to stop and a step length. range(2, 12, 2) would make the code inside the loop run for each of the i values 2 -> 4 -> 6 -> 8 -> 10. The order of the arguments are range(start, stop before, step). The iteration variable can have any name.

total = 0 # declared BEFORE the loop!

for number in range(2, 12, 2):
    print(number)
    
    total += number # updating INSIDE the loop
    
print(f"The total is {total}") # printing AFTER the loop
2
4
6
8
10
The total is 30

In-Class For-loop Exercises

a) Write a program which prints “Karma” 5 times. Then “Chameleon” 1 time. Then “You come and go” 2 times. Use loops for all repeated printing!

b) Using a for loop with a start, stop and step lenght, calculate the sum of all odd numbers from 1 to and including 101. To make sure you have the right approach, you can try from 1 to 7 first.

c) Were both of these exercises a good use of loops?


Iterating through a list

A very useful use-case for a for loop is iterating through a list. Instead of making the iteration variable the numbers that the range() function gives us, we can make it go through the elements of a list using the in keyword.

myList = [5, 30, 7, 2]

for element in myList:
    print(element)
5
30
7
2

Just like how you can put multiple if sentences inside eachother, you can put a for loop inside another for loop.

for i in range(2): #i is 0 then 1
    for j in range(3): #j is 0 then 1 then 2
        print(f"i = {i} -- j = {j}")
i = 0 -- j = 0
i = 0 -- j = 1
i = 0 -- j = 2
i = 1 -- j = 0
i = 1 -- j = 1
i = 1 -- j = 2

In-Class Looping Through Lists Exercises

a) Create a list of five names, then iterate through it printing out each name with a greeting.

b) Extend the previous program so that the greeting is different if the name is your name.

c) Create a list with five numbers, then calculate the total of all the numbers.

d) Create a list with five numbers, then calculate the average.


Changing a String

We can loop over all the characters in a string. Note that the spacings are characters as well.

s = "Today is a fine day"

for character in s:
    print(character)
T
o
d
a
y
 
i
s
 
a
 
f
i
n
e
 
d
a
y

Say that we want to replace all the empty spaces in the string with new lines, "\n". This can easily be done by making use of the replace-function in Python, as shown in the example below.

s_new = s.replace(" ", "\n")
print(s_new)
Today
is
a
fine
day

The replace function can change all appearances of one substring to another substring.

print(s.replace("Today is", "Yesterday was"))
Yesterday was a fine day

Be careful, as replace changes all appearences of a substring, not just the first!

print("What? Where? When?".replace("W", "T"))
That? There? Then?

This can be very useful for removing puncuation and special characters we are not interested in.

print("What? Where? When?".replace("?", ""))
What Where When

Sometimes, for example when one wants to count all words that are similar, it can be useful to change the whole string into lower or upper case letters, or to a string with title-format. This can be done by making use of the upper, lower and title commands, as illustrated in the following lines.

print(s.upper())
TODAY IS A FINE DAY
print(s.lower())
today is a fine day
print(s.title())
Today Is A Fine Day

If we want to remove empty space at the ends of a string, we can make use of the function strip.

t = "   This string has some unwanted spaces at the ends!       "
print(t.strip())
This string has some unwanted spaces at the ends!

One can also use the functions lstrip and rstrip to remove the empty space on the left and rightmost part of the string, respectively.


In-Class Changing a String Exercises

a) Write a program which prints the following:

Give me a t
Give me a e
Give me a s
Give me a t
What´s that spell? test!

so that any word can take the place of test in the spelling and the end.

b) Start with the string: Good Night, Good night! Parting is such sweet sorrow, that I shall say good night till it be morrow. . Create new strings by

  • removing empty spaces at both ends;

  • removing all punctuation;

  • making all words lower case.

This can make the text much easier to analyze and do statistics on.


Lists of strings

Another useful tool when it comes to string manipulations, is the split-function. This function splits a string into substrings that become elements of a list, as shown below.

s.split()
['Today', 'is', 'a', 'fine', 'day,', 'but', 'yesterday', 'was', 'better']

When nothing else is specified, the default is that the string is split by the empty spaces in the string. In the example above, this means that the sentence is split into elements that make up the words of the sentence. One may also want to split the sentence with respect to other characters, such as clauses and paragraphs. If we want to split the sentence “Today is a fine day, but yesterday was better” into the two clauses making up the sentence, we can use the following argument:

s = "Today is a fine day, but yesterday was better" 
sent = s.split(",")
print(sent)
['Today is a fine day', ' but yesterday was better']

The opposite operation to the split-function is the join-function in Python. It joins string-elements of a list to one string.

s2 = " ".join(["This", "is", "a", "list", "of", "strings"])
print(s2)
This is a list of strings

The function join takes exactly one argument. This argument tells the computer what to be joined. In the case above, we wanted to join the elements in the list words. The argument " " in front of join tells the computer that it shall bind the different elements of the given list together using empty spacing. Note that some space is left between the quotation marks. If one instead wants to bind each word together with a "\n", one simply writes this in front of the operation, as shown below.

s3 = "\n".join(words)
print(s3)
Today
is
a
fine
day

If you have a string of multiple lines, you can split the lines by making use of split("\n") on a Linux or Mac, and split("\r\n") on Windows, or just use the more general splitlines-function. This function is used in the following example.

string = "first line \nsecond line \nthird line"
print(string)
first line 
second line 
third line
string.splitlines()
['first line ', 'second line ', 'third line']

In-Class Lists of strings Exercises

Given the string: And then she was like "no!", and then I was like "what?", and then I just left because I just couldn't even.

a) Split it into a list of strings by empty spaces.

b) Use your code from earlier to again

  • Remove spaces at the ends

  • Remove all punctuation and quotation marks

  • Make all words lower case

Then split the text into a list of strings by empty spaces.

c) Which list of strings is the easiest to work with if you want to analyze the length and diversity of words in a text?