## Module #8

Lists are the primary 'sequence object' in Python which allows you to store an almost infinite number of values within a single identifier. This module introduces you to the basics of using Lists in Python as well as a number of different kinds of problems that can be easily solved using a variety of list-specific functions and methods.

### List Basics

#### Sequence Objects

The programs that we have written so far have been designed to operate using textual data (strings), logical data (booleans) and numeric data (integers and floating Point numbers). These data types have the ability to represent and store one piece of data at a time - for example:

```x = 5			# integer
y = 5.0			# floating point number
z = 'hello'		# string
q = True		# boolean```

However, there are times when we need to write a program that keeps track of many values at the same time. For example, if we wanted to write a program to keep track of final exam scores for a group of 50 students in a class we would need to create 50 different variables, like this:

```test_01 = 95.45
test_02 = 89.35
test_03 = 76.43
...
...
test_50 = 97.11```
One way to solve this problem is to use a "sequence" data type, which has the ability to hold multiple values within the same identifier. In many programming languages we call these "arrays," but in Python we refer to this data type as a `list`.

#### List Basics

An easy way to think about a `list` in Python is to think about how a book operates in the real world. A book is a single object (i.e. "Harry Potter and the Chamber of Secrets") that can contain any number of sub-items (i.e. pages).

You can create a `list` in Python by using square brackets, which almost look like the covers of a book in the real world. For example:

`my_book = ["Page 1", "Page 2", "Page 3"]`
The above code will create a new `list` in Python that holds three strings – "Page 1", "Page 2" and "Page 3" – in that order.

Lists can contain any data type that we have covered so far - for example:

`my_list = [100, 200, 300]`

Lists can also mix data types.

`my_list = ['Craig', 5.0, True, 67]`

You can print the value of a `list` using the `print` function. This will print all of the values stored in the `list` in the order in which they are represented:

```my_list = ["a", "b", "c"]
print (my_list)```

Just like with a string, you can use the repetition operation (`*`) to ask Python to repeat a list. For example:

```my_list = [1, 2] * 3
print (my_list)

#>> [1, 2, 1, 2, 1, 2]
```

You can use the concatenation operation (`+`) to ask Python to combine lists, much like how you would combine two strings. For example:

```my_list = [1, 2] + [99, 100]
print (my_list)

# >> [1, 2, 99, 100]
```

#### Indexing List Elements

In a book, you can reference a page by its page number and in a `list` you can reference an element stored in a list using its index. Indexes are integer values that represent the position of an item within a list. Indexes always start at zero (the same way a string index begins at zero). For example:

```my_list = ["Apple", "Pear", "Peach"]
print (my_list)

# >> Apple
```
You will raise an exception if you attempt to access an element outside the range of a `list`. For example:
```my_list = ["Apple", "Pear", "Peach"]
print (my_list) # Index doesn’t exist!```

Lists are "mutable" data types, which means that they can be changed once they have been created (unlike strings). If you know the index of an item you wish to change, you can simply use the assignment operator to update the value of the item at that position in the `list`. For example:

```my_list = [1, 2, 3]
print (my_list)
# >> [1,2,3]

my_list = 99
print (my_list)
# >> [99,2,3]```

Sample program: This program demonstrates list creation, repetition, concatenation and accessing individual elements within a `list`.

### Working with Lists

#### Iterating over a List

When working with lists you will often need to access many or all of the elements within a `list` to solve a certain problem. For example, imagine that you had the following list of price values:

```prices = [1.10, 0.99, 5.75]
```

If you wanted to compute 7% sales tax on each price you would need to access each item in the list and multiply it by 0.07. For a `list` with three elements this is pretty easy:

```tax_0 = prices * 0.07
tax_1 = prices * 0.07
tax_2 = prices * 0.07```

However, as your lists become larger and larger this technique will become unmanagable (imagine you had 1,000 prices in the list!) -- the solution to this problem is to use a repetition structure to iterate over the contents of the `list`.

The simplest way to iterate over a `list` is to use a `for` loop to iterate over all items in the `list`. When you do this, the target variable of your loop assumes each value of each element of the `list` in order.

Sample Program: The program below demonstrates how to quickly iterate over a `list` using a `for` loop.

Programming Challenge: Given the list below, write a program that counts the # of A’s (scores between 90 and 100). Extension: Count the # of B’s, C’s, D’s and F’s. Click the "Run" button to check your work, and click here to download the solution.

As you can see, a `for` loop is a convenient way to sequentially iterate through a `list`. The target variable in a `for` loop assumes the value of the current item in the list as you iterate. However, the target variable isn’t very helpful if you want to change the value of an item in a `list` since it just represents a copy of the data. For example:

Sample Program: The list below remains unchanged because we are not modifying the values stored in the `list`.

In order to change a `list` item you need to know the index of the item you wish to change. You can then use that index value to change an item at a given position in the `list`. For example:

Sample Program: The list below does change because we are using index notation to change a value at a particular position in the list.

There are two main techniques for iterating over the index values of a `list`:

• Setting up a counter variable outside the `list` and continually updating the variable as you move to the next position in the `list`
• Using the `range` function to create a custom range that represents the size of your `list`

If you set up an accumulator variable outside of your loop, you can use it to keep track of where you are in a `list`. For example:

Sample Program: Using an accumulator variable to keep track of our current position in a list.

To improve upon this example, we can use the `len` function to determine the size of our `list` (rather than just hard coding our loop to end after 3 iterations). The `len` function can take a `list` as an argument and will return the integer value of the size of the `list`. Example:

Sample Program: Using the `len` function to count the number of elements in a `list` and then using that result to control our loop.

You can also use the `range` function to construct a custom range that represents all of the indexes in a `list`. This technique can be a bit cleaner to implement since you don't need to worry about setting up and maintaining a counter variable:

Sample Program: Use the `range` function to create a custom range that represents all valid positions in a `list`.

Programming Challenge: Given the following list of student test scores, apply a class "curve" to each score. The class curve is as follows:

• 90 or above: no curve
• 80 to 90: +2 points
• 70 to 80: +5 points
• Lower than 70: +8 points

#### Creating Lists

You can create an empty `list` with no elements using the following syntax:

```mylist = []
```

With an empty `list`, you cannot place content into the `list` using index notation since there are no "slots" available to be used in the `list`. You can, however, append values to the list using the concatenation operator, like this:

```mylist = []
mylist += ["hello"]
mylist += ["world"]
print (mylist)

# >> ["hello","world"]```

Since you cannot access an element outside of the range of a `list` it is sometimes necessary to set up a correctly sized list before you begin working with it. For example:

```# create a list of 7 zeros
daily_sales =  * 7```

Programming Challenge: Write a program that asks the user for daily sales figures for a full week (Sunday – Saturday). Store these values in a list and print them out at the end of your program. Here's a sample running of your program:

```Enter sales for Day #1: 100
Enter sales for Day #2: 200
Enter sales for Day #3: 300
Enter sales for Day #4: 400
Enter sales for Day #5: 500
Enter sales for Day #6: 600
Enter sales for Day #7: 700

Sales for the week:  [100,200,300,400,500,600,700]```

#### Slicing Lists

Sometimes you need to extract multiple items from a `list`. Python contains some built in functions that make it easy for you to “slice” out a portion of a list. The syntax for `list` slicing is identical to the syntax for string slicing. To slice a `list` you use a series of "slice indexes" to tell Python which elements you want to extract. Example:

`new_list = old_list[start:end]`

Python will copy out the elements from the list on the right side of the assignment operator based on the start and end indexes provided. It will then return the result set as a new `list`. Note that slice indexes work just like the `range` function – you will grab items up until the end index, but you will not grab the end index itself. Here's an example:

```list_1 = ['zero', 'one', 'two', 'three', 'four', 'five’]
list_2 = list_1[1:3]
print (list_1)
print (list_2)

# >> ['zero', 'one', 'two', 'three', 'four', 'five’]
# >> ['one', 'two']```

If you omit the start_index in a slice operation, Python will start at the first element of the `list`. If you omit the end_index in a slice operation, Python will go until the last element of the `list`. If you supply a third index, Python will assume you want to use a step value. This works the same as the step value you would pass to the `range` function

Programming Challenge: Given the following `list`, write a program that does the following:

• Extract the first 3 elements of the list into a new list
• Extract the characters b, c, and d into a new list
• Extract the last 4 characters into a new list

#### Finding items in a list

You can easily test to see if a particular item is in a `list` by using the `in` operator. Here’s an example:

```my_list = ['pie', 'cake', 'pizza']

if 'cake' in my_list:
print ("I found cake!")
else:
print ("No cake found.")```

The `in` operator lets you search for any item in a `list`. It will return a Boolean value that indicates whether the item exists somewhere in the `list`.

Programming Challenge: Given the following lists, write a program that lets the user type in the name of a product. If the product name exists in our inventory, you should print out that it is in our inventory. Otherwise you should print out that the product is not found. Ensure that your program is case insensitive (i.e. searches for "Apple" or "apple" or "APPLE" should all succeed). Click the "Run" button to check your work, and click here to download the solution.

Programming Challenge: Given these two lists, write a program that finds all elements that exist in both lists (i.e. the integer 2 exists in both lists). Store your results in a list and print it out to the user. The expected answer is:

`[1, 2, 3]`

### List Functions

#### Appending Items to a List

You have already seen a few ways in which you can add items to lists:

• Repeat the `list` using the `*` operator
• Concatenate the list using the `+` operator

Another way to add items to a list is to use the `append` method. The `append` method is a function that is built into the `list` datatype. It allows you to add items to the end of a `list`. Example:

```mylist = ['Christine', 'Jasmine', 'Renee']
mylist.append('Kate')
print (mylist)```

Programming Challenge: Write a program that continually prompts a user to enter in a series of first names. The user can elect to stop entering names when they supply the string "end." Store these first names in a list and print them out at the end of your program. Extension: Prevent the user from entering duplicate names (hint: use the `in` operator). Click the "Run" button to check your work, and click here to download the solution.

#### Removing Items from a List

You can remove an item from a `list` by using the `remove` method. Here’s an example:

```prices = [3.99, 2.99, 1.99]
prices.remove(2.99)
print (prices)```

Note that you will raise an exception if you try and remove an item that is not in the `list`. In order to avoid this, you should make sure to test to see if it is in the list first using the `in` operator, or use a `try / except` block to catch any errors you might raise.

Programming Challenge: Continually ask the user for a product name. Next, see if that product name is included in the inventory list below. If it is, remove the product from the list and then print the current list of products to the user. If the product is not on the list you should alert the user that we do not currently carry the product in question. You can end the program when the list of products is exhausted or when the user types the string "end." Click the "Run" button to check your work, and click here to download the solution.

Sometimes you want to delete an item from a particular position in a `list`. You can do this using the `del` keyword. For example, say you wanted to delete the item in position #0 in the following `list`:

Sample Program: Using the `del` keyword to remove an item from a particular position in a `list`.

#### Re-ordering List Items

You can have Python sort items in a `list` using the `sort` method. Here’s an example:

Sample Program: This program sorts a `list` in ascending alphabetical order.

Python can also reverse the items in a list using the `reverse` method. This method will swap the elements in the `list` from beginning to end (i.e. [1,2,3] becomes [3,2,1]) - note that this method does not sort the `list` at all. It simply reverses the values in the `list`. Here's an example:

Sample Program: This program reverses a `list`.

#### Getting the Location of an Item in a List

You can use the `index` method to ask Python to tell you the `index` of where an item can be found in a `list`. The `index` method takes one argument – an element to search for – and returns an integer value of where that element can be found. Caution: The `index` method will throw an exception if it cannot find the item in the `list`. Here’s an example:

Sample Program: Demonstration of how to find the location of an item in a `list` using the `index` method.

Programming Challenge: The lists below are organized in such a way that the item at position 0 in the first `list` matches with the item at position 0 in the second `list`. With this in mind, write a product price lookup program that works as follows:

```Enter a product:  peanut butter
This product costs 3.99
```

#### Getting the Largest and Smallest Items in a List

Python has two built-in functions that let you get the highest and lowest values in a `list`. They are called `min` and `max` – here’s an example:

Sample Program: Demonstration of how to find the largest and smallest items in a list.

### Quiz

Now that you've completed this module, please visit our NYU Classes site and take the corresponding quiz for this module. These quizzes are worth 5% of your total grade and are a great way to test your Python skills! You may also use the following scratch space to test out any code you want.

### Feedback     