This exercise will walk you through using multi-dimensional lists.
Python lists can contain virtually type of element, include sequential types like lists and dictionaries.
You can create 2D lists a few ways, and we'll cover two:
In Python, you can create a list by using []
and setting elements between them. You can use this method to create 2D lists as well:
oneDList = ["hello", "goodbye"]
twoDList = [["hello", "goodbye"], ["bonjourno", "ciao"]]
print(oneDList)
print(twoDList)
For 1D lists, you can access elements using [x]
on an existing list (as long as x
is within bounds of the list's length).
In 2D lists, you do the same thing but twice:
print(twoDList[0][1])
twoDList[1][0] = "mi scusi"
print(twoDList)
Spreadsheets like you see in Excel are a good way to conceptualize 2D lists. When we use the twoDList[x][y]
accessor, you can think of x
as the row and y
as the column.
This conceptualization makes fits well if you spread your list declaration across multiple lines:
bigTwoDList = [
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
["0", "1", "2", "3", "4"],
[100, 101, 102, 103, 104],
[9, 8, 7, 6, 42],
]
print(bigTwoDList)
row = 3
col = 4
print("Row: %d, Col: %d =" % (row,col), bigTwoDList[row][col])
You can iterate through the list using nested for loops:
for i in bigTwoDList:
for j in i:
print(j)
If you have a rectangular 2D list (i.e., all rows have the same number of columns) and know its dimensions, you can use the range()
function we've seen so much:
rows = 5
cols = 5
for i in range(rows):
for j in range(cols):
print("Row: %d, Col: %d =" % (i,j), bigTwoDList[i][j])
Nothing requires your lists be rectangular. You can create 2D lists with varying sizes:
raggedTwoDList = [
[0, 1, 2, 3, 4],
[0, 1, 2,],
["0", "4"],
[100, 101, 102, 103, 104, 77, 44, 44, 44],
[9],
]
print(raggedTwoDList)
You'll notice that calling print()
on a 2D list doesn't provide you a very understandable/attractive string representation.
Write a function my_pretty_print()
that iterates through a given 2D list and prints all content in the same row on the same line with a new line between each row.
For example:
twoDList = [[0,1,2,3,4],[5,6,7,8,9],[1,3,5,7,9],[0,2,4,6,8]]
my_pretty_print(twoDList)
0 1 2 3 4
5 6 7 8 9
1 3 5 7 9
0 2 4 6 8
### Implement Here
def my_pretty_print(twoDList):
"""Pretty-print a 2d list"""
for row in twoDList:
for colElement in row:
print(colElement, end=" ")
print()
Now that we've worked with 2D lists a bit, how can we make them a little more dynamic? That is, given a number of rows and a number of columns as input, what is the correct way to create a 2D list?
You might be tempted to use Python list's duplication feature like so:
# Try, and FAIL, to create a variable-sized 2d list
rows = 3
cols = 3
a = [ [0] * cols ] * rows # Error: creates shallow copy
# Creates one unique row, the rest are aliases!
print("This SEEMS ok. At first:")
my_pretty_print(a)
#### BAADDDDDD ######
a[0][0] = 42
print("But see what happens after a[0][0]=42")
my_pretty_print(a)
The error above is caused by the outer-most duplication, where a list is duplicated using * rows
. This error stems from Python's creating an alias (i.e., identical) of the list on the left of the * rows
.
Rather use the *
operator to create 2D lists, you should use the list append()
function or the list +
operator to add rows to your 2D list:
# Create a variable-sized 2d list
rows = 3
cols = 3
a=[]
for row in range(rows):
a += [[0]*cols]
print("This IS ok. At first:")
my_pretty_print(a)
a[0][0] = 42
print("And now see what happens after a[0][0]=42")
my_pretty_print(a)
Write a function make_2d_list()
that takes as arguments a number of rows and a number of columns. This function should create and return a rectangular 2D list with the dimensions (rows x columns), and each cell should be initialized to 0.
For example:
my2dList = make_2d_list(5,3)
my_pretty_print(my2dList)
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
Test the resulting 2D list to make sure you can assign a value to one element (and ONLY one element):
my2dList[2][1] = 9000
my_pretty_print(my2dList)
0 0 0
0 0 0
0 9000 0
0 0 0
0 0 0
### Implement Here
def make_2d_list(rows, columns):
"""Create a 2d list"""
new2dList = []
for row in range(rows):
newRow = []
for col in range(columns):
newRow.append(0)
new2dList.append(newRow)
return new2dList
def make_2d_list_v2(rows, columns):
"""Create a 2d list"""
new2dList = []
for row in range(rows):
new2dList.append([0] * columns)
return new2dList
my2dList = make_2d_list_v2(5,3)
my_pretty_print(my2dList)
print()
my2dList[2][1] = 9000
my_pretty_print(my2dList)
Now you can use this function create an NxN
matrix and set its values to some useful numbers.
In this exercise, create a 12x12 2D list, and use a for loop to set the values to the products of the (1+row) and (1+column). You should end up with a 12x12 multiplication table.
n = 12
#### IMPLEMENT HERE
multTable = make_2d_list(n, n)
for row in range(n):
for col in range(n):
multTable[row][col] = (row+1) * (col+1)
my_pretty_print(multTable)
2D lists are similar to images. As such,you can use matplotlib
to view them.
Matplotlib has a function called imshow()
that will take multi-dimensional data and show it as a plot:
%matplotlib inline
import matplotlib.pylab as plt
my2dList = make_2d_list_v2(10,15)
plt.imshow(my2dList)
plt.show()
Matplotlib's imshow()
function, when called with a 2D list, will interpolate between the highest and lowest values to show you different colors.
Try running imshow()
on the multiplication table you made.
plt.imshow(multTable)
plt.show()
Naturally, a 2D list of all zeros is not very interesting.
Play with the values in your 2D list to get something that looks like the following:
my2dList = make_2d_list_v2(10,15)
my2dList[8][3:10] = [255] * 7
my2dList[7][2:11] = [255] * 9
my2dList[6][2:12] = [255] * 10
my2dList[5][2:4] = [255] * 2
my2dList[5][11:13] = [255] * 2
my2dList[5][7] = 255
my2dList[4][7] = 255
my2dList[3][4:9] = [255] * 5
my2dList[2][4:9] = [255] * 5
my2dList[1][4:9] = [255] * 5
my2dList[0][7] = 255
my_pretty_print(my2dList)
plt.imshow(my2dList)
plt.show()
You'll notice the image above is uniformly purple. This coloring is an artifact of matplotlib's interpreting the values in your 2D list. You can change the colors using the cmap=
color map named argument.
By default, the color map is a lookup table lut
. You can use others, as shown here:
plt.imshow(my2dList, cmap="inferno")
plt.show()