A list is a row of data: one item after another, each with its own index. That is fine for the names of five players. It is not enough for their scores in four spelling tests, because that data has two directions. Down the page there is one line per student, and across the page there is one column per test.
Bob 5 9 10 7
Mary 4 10 3 6
James 7 6 4 8
Data shaped like a table is stored in a 2D array, where 2D stands for two dimensional: it has rows and it has columns.
2D array is the name the exam specification uses. Python does not have a separate kind of data for it. It builds a 2D array out of what you already know from the Lists chapter: a list of lists. The outer list holds the rows, and each row is an ordinary list holding the items on that row.
Each row is written as a list, in square brackets, and the rows are written inside one more pair of square brackets, with a comma between them:
animals = [["Salmon", "Pollock", "Cod"],
["Parrot", "Duck", "Wren"],
["Camel", "Lion", "Tiger"]]
That is one identifier, animals, holding three rows of three items: fish on
the first row, birds on the second and land animals on the third.
Python does not mind the line breaks inside the brackets, so a 2D array is usually written one row per line. It is still one assignment, and laid out this way the code looks like the table it stores.
To pick out one item you need two numbers: which row it is on, and where it is on that row. Both count from zero, exactly like the index of an ordinary list.
| Column 0 | Column 1 | Column 2 | |
|---|---|---|---|
| Row 0 | "Salmon" |
"Pollock" |
"Cod" |
| Row 1 | "Parrot" |
"Duck" |
"Wren" |
| Row 2 | "Camel" |
"Lion" |
"Tiger" |
The row index comes first and the column index comes second, each in its own pair of square brackets. The first number says how far down to go, the second how far across.
print(animals[1][2])
That prints Wren. Python reads it in two steps, left to right: animals[1]
is the second row, ["Parrot", "Duck", "Wren"], and [2] then picks the
third item from that row.
animals[1][2] and animals[2][1] are different items: Wren and Lion.
Swapping the two indices is the most common mistake with 2D arrays, and Python
will not warn you about it as long as both numbers happen to be valid. Say it to
yourself every time: row first, then column.
One index on its own is allowed too. It gives you a whole row, as a list:
print(animals[0])
['Salmon', 'Pollock', 'Cod']
An item is changed by assigning to it, just like an item in a list. The two indices say which one:
animals[0][2] = "Plaice"
That replaces Cod, the item on row 0 at column 2, with Plaice. Every other
item stays where it is.
Each row is a list, so it has append. Pick the row with one index, then
append to it:
animals = [["Salmon", "Pollock", "Cod"],
["Parrot", "Duck", "Wren"],
["Camel", "Lion", "Tiger"]]
animals[0].append("Trout")
print(animals)
[['Salmon', 'Pollock', 'Cod', 'Trout'], ['Parrot', 'Duck', 'Wren'], ['Camel', 'Lion', 'Tiger']]
Trout goes on the end of row 0, so that row now has four items and the other
two still have three. Nothing says every row has to be the same length.
Printing the whole array works the same as printing a whole list, and shows the list of lists for what it is: square brackets inside square brackets.
A row can start out empty and be filled while the program runs. This program keeps asking for words and adds each one to the end of row 0, until the user says they have had enough:
words = [[], []]
words_left = True
while words_left:
print("Enter a word")
word = input()
words[0].append(word)
print("Would you like to enter another word? Y/N")
answer = input().upper()
if answer == "N":
words_left = False
print(words)
A few things in it are worth a closer look.
words = [[], []] is a 2D array with two rows and nothing on either of them
yet. [] is an empty list, as in the Random numbers chapter.words_left holds a Boolean value, True or False, rather than a number
or a piece of text: the two values every condition produces. A variable like
this is called a Boolean variable, and one that a loop keeps checking is
often called a flag. A while loop can check it directly:
while words_left: keeps going for as long as it is True, just like
while words_left == True:. The loop ends once the user answers N and the
variable is set to False. True and False start with a capital letter
and have no quotes around them.input().upper() uses .upper() from the String manipulation chapter, so
n works as well as N.Run it, enter three words, and look at the last line of output. The three words are all on the first row, and the second row is still empty.
index does the opposite of an index. Give it an item, and it tells you where
that item is. Like append, it belongs to one row:
print("Which word would you like to find?")
word = input()
location = words[0].index(word)
If the user types a word that is the third one on row 0, location holds 2.
animals = [["Salmon", "Pollock", "Cod"],
["Parrot", "Duck", "Wren"],
["Camel", "Lion", "Tiger"]]
print(animals[1].index("Duck"))
That prints 1: Duck is at column 1 of row 1. Notice that you have to know
which row to search. animals[1].index("Lion") does not look on the other rows.
index only works for an item that is actually there. Ask for one that is not,
and the program stops with a ValueError, an error saying the item is not in
the list.
Where the item comes from the user, check with in first:
if word in words[0]:. And if the same item is on a row twice, index gives
you the first one.
Make sure that you check for the following things:
animals[1][2], never animals[1, 2].append and index are used on one row, as in animals[0].append("Trout").index is only asked for an item that is on that row.