5.1 Lists
A list is a collection of elements that are ordered and changeable. Lists are defined by enclosing comma-separated elements in square brackets []. Lists can contain elements of different data types, including other lists. In Table 1, we have an example of a list containing integers, strings, and a nested list.
| List example | Description |
|---|---|
["apple", "banana", "cherry"] |
A list of strings. |
[1, 2, 3, 4, 5] |
A list of integers. |
["apple", 1, "banana", 2] |
A list of mixed data types. |
["apple", ["banana", "cherry"], "orange"] |
A list with a nested list. |
[] |
An empty list. |
[[], [], []] |
A list of empty lists. |
[1, [2, [3, [4]]]] |
A nested list with multiple levels. Notice the , separating the elements. |
[[1, 2], [3, 4], [5, 6]] |
A 2D list with three rows and two columns. |
In computer science, the terms array, list, and vector are often used interchangeably to refer to a collection of elements. However, there are subtle differences between them:
- Array: An array is a fixed-size collection of elements of the same data type. Arrays are contiguous blocks of memory, and elements are accessed using an index. In Python, lists are more flexible than traditional arrays because they can store elements of different data types and grow dynamically.
- Vector: A vector is a one-dimensional array that can grow or shrink in size. In some programming languages, vectors are implemented as resizable arrays, similar to Python lists. The term vector is commonly used in mathematical and scientific contexts to represent a one-dimensional array of values.
- List: Lists in Python are similar to arrays in other programming languages but offer additional functionality, such as built-in methods for manipulation and iteration.
In this chapter, we will use the term list to refer to collections of elements in Python.
5.1.1 List slicing
In Python, you can use list slicing to extract a subset of elements from a list. This is similar to string slicing, where you extract a substring from a string. List slicing is done by specifying the start and end indices separated by a colon :, and an optional step size separated by another colon :. The start index is inclusive, and the end index is exclusive. In Table 2, we have examples of list slicing considering the list l = [1, 2, 3, 4, 5].
| List slicing | Description | Example | Result |
|---|---|---|---|
l[start:end] |
Returns a subset of the list from the start index to the end index (excluding the end index). |
l[1:3] |
[2, 3] |
l[:end] |
Returns a subset of the list from the beginning to the end index (excluding the end index). |
l[:3] |
[1, 2, 3] |
l[start:] |
Returns a subset of the list from the start index to the end. |
l[2:] |
[3, 4, 5] |
l[:] |
Returns a copy of the entire list. | l[:] |
[1, 2, 3, 4, 5] |
l[start:end:step] |
Returns a subset of the list from the start index to the end index (excluding the end index) with a specified step size. |
l[1:5:2] |
[2, 4] |
l[::-1] |
Reverses the order of the elements in the list. | l[::-1] |
[5, 4, 3, 2, 1] |
l[::2] |
Returns every second element of the list. | l[::2] |
[1, 3, 5] |
l[-1] |
Returns the last element of the list. | l[-1] |
5 |
l[-2] |
Returns the second-to-last element of the list. | l[-2] |
4 |
l[-3:] |
Returns the last three elements of the list. | l[-3:] |
[3, 4, 5] |
l[:-2] |
Returns all elements except the last two elements of the list. | l[:-2] |
[1, 2, 3] |
l[-1:-4:-1] |
Returns the last three elements of the list in reverse order. | l[-1:-4:-1] |
[5, 4, 3] |
Use Listing 1 to compare several slices of the same list. Change the start, end, or step value and select Run Code again.
5.1.2 Multidimensional lists
A multidimensional list is a list of lists, where each element in the list is itself a list. This allows you to create a matrix or a table-like structure in Python. In Table 3, we have an example of a 2D list representing a matrix.
| Multidimensional list | Description |
|---|---|
[[1, 2, 3], [4, 5, 6], [7, 8, 9]] |
A 2D list representing a 3x3 matrix. |
[[1, 2], [3, 4], [5, 6]] |
A 2D list representing a 3x2 matrix. |
[[1], [2], [3], [4]] |
A 2D list representing a 4x1 matrix. |
[[1, 2, 3], [4, 5], [6, 7, 8, 9]] |
A 2D list with varying row lengths. |
[[[1, 2], [3, 4]], [[5, 6], [7, 8]]] |
A 3D list representing a 2x2x2 cube. |
Remember that you can access elements in a multidimensional list by using multiple indices. For example, to access the element at row i and column j of a 2D list matrix, you can use matrix[i][j]. In Listing 2, we have an example of accessing elements in a 2D list.
Select Run Code to execute the example in your browser. Change an index or one of the values, then run it again to inspect the result.
5.1.3 List methods
Python provides several built-in methods to work with lists. These methods allow you to perform common operations on lists, such as adding elements, removing elements, sorting elements, and more. In Table 4, we have a list of common list methods in Python.
| List method | Description | Example | Result |
|---|---|---|---|
list.append(element) |
Adds an element to the end of the list. | fruits = ["apple", "banana"]; fruits.append("cherry") |
["apple", "banana", "cherry"] |
list.insert(index, element) |
Inserts an element at the specified index. | fruits = ["apple", "banana"]; fruits.insert(1, "cherry") |
["apple", "cherry", "banana"] |
list.remove(element) |
Removes the first occurrence of the specified element from the list. | fruits = ["apple", "banana", "cherry"]; fruits.remove("banana") |
["apple", "cherry"] |
list.pop(index) |
Removes the element at the specified index (or the last element if no index is specified) and returns it. | fruits = ["apple", "banana", "cherry"]; fruits.pop(1) |
["apple", "cherry"] |
list.index(element) |
Returns the index of the first occurrence of the specified element in the list. | ["apple", "banana", "cherry"].index("banana") |
1 |
element in list |
Returns True if the element is present in the list, False otherwise. |
"banana" in ["apple", "banana", "cherry"] |
True |
list.count(element) |
Returns the number of occurrences of the specified element in the list. | ["apple", "banana", "cherry", "banana"].count("banana") |
2 |
list.sort() |
Sorts the elements of the list in ascending order. | fruits = ["banana", "apple", "cherry"]; fruits.sort() |
["apple", "banana", "cherry"] |
list.reverse() |
Reverses the order of the elements in the list. | fruits = ["apple", "banana", "cherry"]; fruits.reverse() |
["cherry", "banana", "apple"] |
list.copy() |
Returns a copy of the list. | fruits = ["apple", "banana", "cherry"]; fruits_copy = fruits.copy() |
["apple", "banana", "cherry"] |
list.clear() |
Removes all elements from the list. | fruits = ["apple", "banana", "cherry"]; fruits.clear() |
[] |
del list[start:end] |
Removes the elements selected by the slice from the list. | numbers = [1, 2, 3, 4]; del numbers[2:] |
[1, 2] |
list + other |
Returns a new list with the elements of other after those of list. |
[1, 2] + [3, 4] |
[1, 2, 3, 4] |
list * n |
Returns a new list that repeats the elements of list n times. |
[0.0] * 3 |
[0.0, 0.0, 0.0] |
len(list) |
Returns the number of elements in the list. | len(["apple", "banana", "cherry"]) |
3 |
max(list) |
Returns the maximum element in the list. | max([3, 1, 4, 1, 5, 9, 2, 6, 5]) |
9 |
min(list) |
Returns the minimum element in the list. | min([3, 1, 4, 1, 5, 9, 2, 6, 5]) |
1 |
sum(list) |
Returns the sum of all elements in the list. | sum([1, 2, 3, 4, 5]) |
15 |
sorted(list) |
Returns a new list with the elements of the original list sorted. | sorted([3, 1, 4, 1, 5, 9, 2, 6, 5]) |
[1, 1, 2, 3, 4, 5, 5, 6, 9] |
list.extend(iterable) |
Extends the list by appending elements from the iterable. | fruits = ["apple", "banana"]; fruits.extend(["cherry", "orange"]) |
["apple", "banana", "cherry", "orange"] |
sorted(list, key=function) |
Returns a new list with the elements of the original list sorted using the specified key function. | sorted(["apple", "banana", "cherry"], key=len) |
["apple", "cherry", "banana"] |
reversed(list) |
Returns an iterator that iterates over the elements of the list in reverse order. | list(reversed(["apple", "banana", "cherry"])) |
["cherry", "banana", "apple"] |
5.1.4 In-place vs. out-of-place operations
In Python, operations on lists can be categorized as in-place or out-of-place operations based on whether the original list is modified or a new list is created. In-place operations modify the original list, while out-of-place operations create a new list without modifying the original list.
- Example 1. Append operation: The
list.append(element)method is an in-place operation because it modifies the original list by adding an element to the end. On the other hand, thelist + [element]operation is an out-of-place operation because it creates a new list by concatenating the original list with another list. - Example 2. Sort operation: The
list.sort()method is an in-place operation because it modifies the original list by sorting the elements in place. In contrast, thesorted(list)function is an out-of-place operation because it creates a new sorted list without modifying the original list. - Example 3. Reverse operation: The
list.reverse()method changes the original list. The built-inreversed(list)returns an iterator that visits its items in reverse order without changing the list. Uselist(reversed(values))when you need a new list with the items in reverse order.
Run Listing 3 to observe which operations change the original list and which ones create a new list.
sorted and reversed calls with the in-place sort and reverse methods.
5.1.5 Exercises
Each exercise can be solved with the indexing, slicing, and list operations in this chapter. None of them needs a loop.
5.1.Q1 Concatenate vectors
Create a function that takes two vectors as input and returns a new vector that is the result of concatenating the elements of the second vector to the end of the first vector. Do not modify either input vector.
Here, a vector is a one-dimensional Python list of numbers. Either input may be empty; the returned list is still a new list.
Complete the supplied function in Listing 4. Keep its signature and use the checks below it.
len(values) returns the number of elements, so len([3, 7]) is 2 and len([]) is 0. List indexing starts at 0: [3, 7][0] is 3. An index must refer to an existing element.
assert condition stops the check with an AssertionError when the condition is false.
5.1.Q2 Count elements
Create a function that takes a vector of numbers and a target value as input and returns the count of occurrences of the target value in the vector.
Here, a vector is a one-dimensional Python list of numbers. Count values equal to the target using ==; an empty list returns 0. Keep the input unchanged.
Complete the supplied function in Listing 5. Keep its signature and use the checks below it.
len(values) returns the number of elements, so len([3, 7]) is 2 and len([]) is 0. List indexing starts at 0: [3, 7][0] is 3. An index must refer to an existing element.
assert condition stops the check with an AssertionError when the condition is false.
5.1.Q3 Search element
Create a function that takes a vector of numbers and a target value as input and returns True if the target value is found in the vector, or False otherwise.
Here, a vector is a one-dimensional Python list of numbers. Match the target with ==. An empty list returns False; keep the input unchanged.
Complete the supplied function in Listing 6. Keep its signature and use the checks below it.
len(values) returns the number of elements, so len([3, 7]) is 2 and len([]) is 0. List indexing starts at 0: [3, 7][0] is 3. An index must refer to an existing element.
assert condition stops the check with an AssertionError when the condition is false.
5.1.Q4 Find maximum element
Create a function that takes a vector of numbers as input and returns the maximum element in the vector.
Here, a vector is a one-dimensional Python list of numbers. Use a nonempty list of finite numbers and keep it unchanged. An empty list has no maximum and is outside this task.
Complete the supplied function in Listing 7. Keep its signature and use the checks below it.
len(values) returns the number of elements, so len([3, 7]) is 2 and len([]) is 0. List indexing starts at 0: [3, 7][0] is 3. An index must refer to an existing element.
assert condition stops the check with an AssertionError when the condition is false.
5.1.Q5 Vector sorting
Create a function that takes a vector of numbers as input and returns a new vector containing the same numbers sorted in ascending order.
Here, a vector is a one-dimensional Python list of finite numbers. Preserve repeated values and leave the input list unchanged. An empty list returns a new empty list.
Complete the supplied function in Listing 8. Keep its signature and use the checks below it.
len(values) returns the number of elements, so len([3, 7]) is 2 and len([]) is 0. List indexing starts at 0: [3, 7][0] is 3. An index must refer to an existing element.
assert condition stops the check with an AssertionError when the condition is false.
5.1.Q6 Vector reversal
Create a function that takes a vector of numbers as input and returns a new vector containing the same numbers in reverse order.
Here, a vector is a one-dimensional Python list of numbers. Leave the input list unchanged. An empty input returns a new empty list.
Complete the supplied function in Listing 9. Keep its signature and use the checks below it.
len(values) returns the number of elements, so len([3, 7]) is 2 and len([]) is 0. List indexing starts at 0: [3, 7][0] is 3. An index must refer to an existing element.
assert condition stops the check with an AssertionError when the condition is false.
5.1.Q7 Append an element to a list
Write a function that adds an element to the end of a list and returns the list. The element can be of any type.
5.1.Q8 Remove the first occurrence from a list
Write a function that removes the first occurrence of an element from a list and returns the list. If the element is not in the list, return the list unchanged.
5.1.Q9 Check whether a list is sorted
Write a Python function is_sorted(values) that returns True when a list of numbers is in ascending order, allowing equal neighboring values, and False otherwise. Do not change the list you receive. Python has a built-in sorted function, but for this exercise use a loop to compare neighboring values. Do not use sorted or the list's sort method.
You may use the starter code in Listing 10. Run the supplied tests, then add one test case of your own and state its expected result.
5.1.Q10 Dynamic vector initialization
Create a function that initializes a dynamic one-dimensional list with a specified size. The function should return the initialized list. Use 0.0 as the initial value of each element.
Use a nonnegative integer size. The returned vector is a one-dimensional Python list. A size of 0 returns an empty list; each call creates a new list.
Complete the supplied function in Listing 11. Keep its signature and use the checks below it.
len(values) returns the number of elements, so len([3, 7]) is 2 and len([]) is 0. List indexing starts at 0: [3, 7][0] is 3. An index must refer to an existing element.
assert condition stops the check with an AssertionError when the condition is false.
5.1.Q11 Redimension dynamic vector
Create a function that takes a dynamic one-dimensional list as input and changes it in place to a new specified size. Preserve the existing data while changing the size. If the list grows, add 0.0 values; if it shrinks, remove values from the end.
Use a nonnegative integer new_size. The vector is a one-dimensional Python list. Keep the same list object, including when resizing to 0, and return None. A request for the current size leaves all values unchanged.
Complete the supplied function in Listing 12. Keep its signature and use the checks below it.
len(values) returns the number of elements, so len([3, 7]) is 2 and len([]) is 0. List indexing starts at 0: [3, 7][0] is 3. An index must refer to an existing element.
assert condition stops the check with an AssertionError when the condition is false. values.extend(other) appends the elements of other to the existing list and returns None. For example, extending [1] with [2, 3] changes it to [1, 2, 3]. A slice values[start:] selects the elements from index start through the end; del values[start:] removes those elements in place.
5.1.M1 Read positions in a nested list
In Listing 13, four variables named a, b, c, and d are read from a nested list. The first index selects a row and the second index selects a column.
In row[::-1], the slice [::-1] makes a new list with the items in reverse order. Python's built-in reversed(row) visits the same items from last to first; list(reversed(row)) also makes a reversed list.
What values do a, b, c, and d contain?
a = 3,b = 7,c = 6, andd = [6, 5, 4].a = 7,b = 3,c = 9, andd = [6, 5, 4].a = 7,b = 3,c = 8, andd = [6, 5, 4].a = 7,b = 3,c = 8, andd = [4, 5, 6].