Lists

Sequences

We've seen numeric types, like int, float and complex. Another kind/classification of type is a sequence. A sequence:

Sequences support operations like:

Strings are Sequences

A string is an ordered sequence of characters. It is a sequence type. It supports:

"blubbins?"[0] #index, first element -> "b" 
"blubbins?"[-1] #index, last element -> "?"
"blubbins?"[1:4] #slices -> "lub"
"blubbins?"[4:] #slices -> "bins?"
"what the " + "blubbins?" # concatenates -> "what the blubbins?"
"blubbins?" * 2 # repeats -> "blubbins?blubbins?"

Lists

A list is another sequence type.

# a list of ints
stuff = [1, "one", 2, "two"]

List Literals

Constructing a list using a list literal looks like this:

["some", "stuff", "between", "brackets"]

Printing Lists

You can pass lists directly to the built-in print function. It will output the list as if it were a string literal:

>>> a = [2, 3, 5, 7]
>>> print(a)
[2, 3, 5, 7]

You can also use str() or string interpolation to create a string representation of a list:

>>> a = [2, 3, 5, 7]
>>> print("Some numbers in a list: %s" % a)
Some numbers in a list: [2, 3, 5, 7]

Built-in List Operators and Functions

Because a list is just another sequence type many of the built-in operators and functions that work with strings behave similarly with lists.

Indexing Operations

What will the following code output? →

import math
land_of_ooo = ["jake", "finn", "princess bubblegum"]
a = -1
print(land_of_ooo[0])
print(land_of_ooo[2])
print(land_of_ooo[a])
print(land_of_ooo[int(math.sqrt(1))])
jake
princess bubblegum
princess bubblegum
finn

Indexing Operations Continued

What will the following code output? →

import math
land_of_ooo = ["jake", "finn", "princess bubblegum"]
a = -1
print(land_of_ooo[3])
print(land_of_ooo[1.0])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not float

Indexing Operations Continued Some More!

Using the list below, How would you retrieve "homer"… once using a positive index, and another time using a negative index? →

simpsons = ["marge", "homer", "lisa"]
simpsons[1]
simpsons[-2]

Indexing Operations Summary

Iterating Over a List

Just like iterating over a sequence of characters…

Iterating Over a List Example

What will the following for loop print out? →

some_boolean_values = [True, True, False]
for b in some_boolean_values:
	print(b)
True
True
False

Slicing

Slicing also works on lists. What will the folloing code output? →

colors = ["red", "green", "blue", "taupe"]
print(colors[0:2])
print(colors[2:])
print(colors[:3])
print(colors[0:100])
['red', 'green']
['blue', 'taupe']
['red', 'green', 'blue']
['red', 'green', 'blue', 'taupe']

Slicing Summary

Again… like slicing strings.

Equality Operators

Lists are compared lexicographically using comparison of corresponding elements; to be equal each element must compare equal and the two sequences must be of the same type and have the same length.

Equal or not equal?

print([1, 2, 3] == [1, 2, 3])
print(['a', 'b', 'c'] == [1, 2, 3])
print(['a', 'b', 'c'] != [1, 2, 3])
True
False
True

Greater Than, Less Than

If not equal, the sequences are ordered the same as their first differing elements.

Equal or not equal?

['a', 'b', 1, 2] > ['b', 'b', 1, 2]
[5, 2] < [5, 2, 1]
['x', 'y', 'z'] < ['x', 'a', 'z']
False
True
False

Addition and Multiplication

Multiplication and addition of lists are similar to the same operations on strings. What will the following code output? →

toppings = ["mushrooms", "peppers", "onions"]
numbers = [2, 3, 5, 7]
print(toppings + numbers)
print(toppings * 2)
print(numbers * 2)
["mushrooms", "peppers", "onions", 2, 3, 5, 7]
["mushrooms", "peppers", "onions", "mushrooms", "peppers", "onions"]
[2, 3, 5, 7, 2, 3, 5, 7]

Addition and Multiplication Summary

len()

You can still use the built-in function, len, on lists. What do you think the following code will output? →

a = ["foo", "bar", "baz"]
b = []
c = ["foo", "bar", "baz", [1, 2, 3]]
print(len(a))
print(len(b))
print(len(c))
3
0
4

Mutability

Unlike strings, however, lists are mutable. That means that you can reassign a value at an index! What will the following code print out? →

>>> a = [3, 4, 5]
>>> a[0] = "surprise"
>>> print(a)
['surprise', 4, 5]

List Methods

Lists are objects, and they have a slew of methods that you can call on them. However, because lists are mutable, many methods actually change the list in place! Let's see how this differs from strings:

>>> s = 'hello'
>>> s.upper()
'HELLO'
>>> print(s)
hello
>>> numbers = [5, 3, 4]
>>> numbers.sort()
>>> print(numbers)
[3, 4, 5]

List Methods Continued

So…. why does this matter?

Some methods that you can call on lists

li = [1, 2, 3]

Adding Elements

  1. append(object) - append object to end of list, even another list!
  2. extend(iterable) - appends all items of one iterable (list, string, etc.) to the list the method was called on
  3. insert(index, object) - insert object before index

Removing Elements

  1. remove(object) - removes first occurrence of object in list
  2. pop() - returns and removes the last element, takes an optional argument to specify index

Miscellaneous Methods

  1. sort() - sorts a list in place →
  2. count(object) - counts the number of occurrences of object in the original list →
  3. index(object) - returns the index of the object supplied; causes an error if the object doesn't exist →

Some Exercises

Make the First Element Last

Make the First Element Last Solution v1

def last_to_first(items):
	""" makes last element in list first, shifts every other element up one """
	if len(items) <= 1:
		return items
	else: 
		return [items[-1]] + items[0:-1]

assert [1] == last_to_first([1]), 'test that one element returns same list'
assert [] == last_to_first([]), 'test that empty list returns empty list'
assert [4, 1, 2, 3] == last_to_first([1, 2, 3, 4]), 'test that all elements shifted by one'

Make the First Element Last Solution v2

def last_to_first(items):
	""" makes last element in list first, shifts every other element up one """
	new_items = items[:]
	if len(items) > 1:
		new_items.insert(0, new_items.pop())
	return new_items


assert [1] == last_to_first([1]), 'test that one element returns same list'
assert [] == last_to_first([]), 'test that empty list returns empty list'
assert [4, 1, 2, 3] == last_to_first([1, 2, 3, 4]), 'test that all elements shifted by one'

Filtering a List

Implement a function called more_characters_than: →

Filtering a List Example Output

print(more_characters_than(["zebra", "cow", "tiger"], 4))
['zebra', 'tiger']

Filtering a List Solution

(btw, there's already a filter function in Python)

def more_characters_than(words, min):
	new_list = []
	for word in words:
		if len(word) > min:
			new_list.append(word)
	return new_list

assert ['zebra', 'tiger'] == more_characters_than(["zebra", "cow", "tiger"], 4), "only strings with more than 4 characters"
assert [] == more_characters_than([], 4), "an empty list returns an empty list"

Average

Implementing Average

def average(numbers):
	sum = 0
	for n in numbers:
		sum += n
	return sum / len(numbers)

assert 9 == average([2, 3, 4]), "takes a list of integers and returns the average value"

Using the built-in sum:

def average(numbers):
	return sum(numbers) / len(numbers)

Looking for something?

Testing for membership within a list is similar to testing for a character in a string. Use the in operator. It returns True if the operand on the left is an element in the list on right. What does the following code print out? →

print('c' in ['a','b', 'c'])
print('c' not in ['a', 'b', 'c'])

breakfast = ["oatmeal", "tofu scramble", "ramen"]
if "ramen" in breakfast:
	print("ramen for breakfast")
else:
	print("wise decision")
True
False
ramen for breakfast

Deleting List Items

You can delete list items using del statement:

What does the following code print out? →

vegetables = ["broccoli", "cauliflower", "brownie sundae", "carrot"]
del vegetables[2]
print(vegetables)
['broccoli', 'cauliflower', 'carrot']

Strings to Lists and Back

There are two useful string methods that are often used with lists:

comics = "ranma,maison ikkoku,scott pilgrim"
awesome_comics_list = comics.split(",")
print(awesome_comics_list)
print(" and ".join(awesome_comics_list))
['ranma', 'maison ikkoku', 'scott pilgrim']
ranma and maison ikkoku and scott pilgrim

Split and Join

If I have the following list, how do I put together each element with an exclamation point and space between each element? How do I turn the resulting string back to a list? →

hello = ["Bill", "Phil", "Gil", "Jill"]
names = "! ".join(hello)
print(names)
print(names.split("! "))

Random - Choice, Shuffle

The random module offers some methods that can be used on lists:

Let's try using a couple of these methods →

import random
numbers = [1, 2, 3, 4, 5, 6, 7]
print(random.choice(numbers))
random.shuffle(numbers)
print(numbers)