Lists 2 - operators
Download exercises zip
There are several operators to manipulate lists. The following ones behave like the ones we’ve seen in strings:
Operator |
Syntax |
Result |
Meaning |
---|---|---|---|
|
|
Return the list length |
|
list |
obj |
Reads/writes an element at the specified index |
|
list |
|
Extracts a sublist - return a NEW list |
|
obj |
|
Cheks if an object is contained in the list |
|
list |
|
Concatenates two lists - return a NEW list |
|
|
|
Given a list of numbers, return the greatest one |
|
|
|
Given a list of numbers, returns the smallest one |
|
|
|
Given a list of numbers, sums all of them |
|
list |
|
Replicates the list - return a NEW list |
|
|
|
Cheks whether lists are equal of different |
What to do
Unzip exercises zip in a folder, you should obtain something like this:
lists
lists1.ipynb
lists1-sol.ipynb
lists2.ipynb
lists2-sol.ipynb
lists3.ipynb
lists3-sol.ipynb
lists4.ipynb
lists4-sol.ipynb
lists5-chal.ipynb
jupman.py
WARNING: to correctly visualize the notebook, it MUST be in an unzipped folder !
open Jupyter Notebook from that folder. Two things should open, first a console and then a browser. The browser should show a file list: navigate the list and open the notebook
lists2.ipynb
Go on reading the exercises file, sometimes you will find paragraphs marked Exercises which will ask to write Python commands in the following cells.
Shortcut keys:
to execute Python code inside a Jupyter cell, press
Control + Enter
to execute Python code inside a Jupyter cell AND select next cell, press
Shift + Enter
to execute Python code inside a Jupyter cell AND a create a new cell aftwerwards, press
Alt + Enter
If the notebooks look stuck, try to select
Kernel -> Restart
Length of a list
A list is a sequence, and like any sequence you can use the function len
to obtain the length:
[2]:
a = [7,5,8]
[3]:
len(a)
[3]:
3
[4]:
b = [8,3,6,4,7]
[5]:
len(b)
[5]:
5
If a list contains other lists, they count as single elements:
[6]:
mixed = [
[4,5,1],
[8,6],
[7,6,0,8],
]
[7]:
len(mixed)
[7]:
3
WARNING: YOU CAN’T use len
as a method
[3,4,2].len() # WRONG
EXERCISE: Try writing [3,4,2].len()
here, which error appears?
[8]:
# write here
EXERCISE: Try writing [3,4,2].len
WITHOUT the round parenthesis at the end, which error appears?
[9]:
# write here
QUESTION: If x
is some list, by writing:
len(len(x))
what do we get?
the length of the list
an error
something else
[10]:
# write code here
QUESTION: Look at this expression, without executing it. What does it produce?
[len([]), len([len(['a','b'])])]
an error (which one?)
a number (which one?)
a list (which one?)
Try writing the result by hand, and then compare it with the one obtained by executing the code in a cell.
Show answerQUESTION: Look at this expression, without executing it. What does it produce?
len([[[],[]],[],[[[]]],[[],[]]])
an error (which one?)
a number (which one?)
a list (which one?)
QUESTION: What does the following expression produce?
[[((len('ababb')))],len(["argg",('b'),("c")]), len([len("bc")])]
Reading an element
Like for strings, we can access an element a list element by putting the index of the position we want to access among square brackets:
[11]:
# 0 1 2 3
la = [70, 60, 90, 50]
As for any sequence, the positions start from 0
:
[12]:
la[0]
[12]:
70
[13]:
la[1]
[13]:
60
[14]:
la[2]
[14]:
90
[15]:
la[3]
[15]:
50
Like for any string, if we exaggerate with the index we get an error:
la[4]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-134-09bfed834fa2> in <module>
----> 1 la[4]
IndexError: list index out of range
As in strings, we can obtain last element by using a negative index:
[16]:
# 0 1 2 3
la = [70, 60, 90, 50]
[17]:
la[-1]
[17]:
50
[18]:
la[-2]
[18]:
90
[19]:
la[-3]
[19]:
60
[20]:
la[-4]
[20]:
70
If we go beyond the list length, we get an error:
la[-5]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-169-f77280923dce> in <module>
----> 1 la[-5]
IndexError: list index out of range
QUESTION: if x
is some list, by writing:
x[0]
what do we get?
the first element of the list
always an error
sometimes an element, sometimes an error according to the list
[21]:
# write code here
QUESTION: if x
is some list, by writing:
x[len(x)]
what do we get?
an element of the list
always an error
sometimes an element, sometimes an error according to the list
Exercise - Gutenberg apprentice
Such honor! So young and you have been hired as master Gutenberg apprentice! Your job is to compose the pages with the characters made with iron blocks, so your collaborators can then send everything to the printing press.
You have a chars
list in which the original blocks are saved. Can you print the writing Gutenberg
?
DO NOT write characters nor additional strings (so no
'g'
nor'G'
!)every character MAY be reused more than once
[22]:
chars = ['b', 'e', 'g', 'n', 'r', 't', 'u'] # Gutenberg
#chars = ['a', 'm', 's', 'p', 'o', 'a', 't'] # Stampamos
l = chars # Let's create a new handy variable
# write here
Writing an element
Since all the lists are MUTABLE, given a list object we can change the content of any cell inside.
For example, suppose you want to change the cell at index 2
of the list la
, from 6
to 5
:
[23]:
#0 1 2 3
la = [7, 9, 6, 8]
We might write like this:
[24]:
la[2] = 5
[25]:
la
[25]:
[7, 9, 5, 8]
Let’s see what’s happening with Python Tutor:
[26]:
# WARNING: FOR PYTHON TUTOR TO WORK, REMEMBER TO EXECUTE THIS CELL with Shift+Enter
# (it's sufficient to execute it only once)
import jupman
[27]:
# 0 1 2 3
la = [7, 9, 6, 8]
la[2] = 5
jupman.pytut()
[27]:
As you see, no new memory regions are created, it just overwrites an existing cell.
Exercise - a jammed parking lot
You are the administrator of the condominum “The Pythonic Joy”. Every apartment has one or two parking spaces assigned, and each one is numbered from 1
to 11
.
What follows is the current parking lot, and as you can see there are three spaces not assigned, because the flats 3
, 4
and 7
have no tenants anymore:
[28]:
parking_lot = ["Carlo", "Apt.3", "Ernesto", "Apt.4", "Apt.7", "Pam", "Giovanna", "Camilla", "Giorgia", "Jessica", "Jim"]
To keep the order you decide to compact the assignments and leave the empty spaces at the far end (could be handy for parking the movers!)
Write some code to MODIFY parking_lot
so to have:
>>> print(parking_lot)
['Carlo', 'Jessica', 'Ernesto', 'Jim', 'Giorgia', 'Pam', 'Giovanna', 'Camilla', 'App.7', 'App.3', 'App.4']
DO NOT create new lists (no
[a,b, ...]
norlist(a,b,...)
)DO NOT write tenants nor apartment names (so no
'Jessica'
nor'Apt.3'
)parking_lot
may have variable lengthassume the unassigned places are always 3 and in fixed position
[29]:
parking_lot = ["Carlo", "Apt.3", "Ernesto", "Apt.4", "Apt.7", "Pam", "Giovanna", "Camilla", "Giorgia", "Jessica", "Jim"]
#result: ['Carlo', 'Jessica', 'Ernesto', 'Jim', 'Giorgia', 'Pam', 'Giovanna', 'Camilla', 'Apt.7', 'Apt.3', 'Apt.4']
#parking_lot = ["Cristian", "Apt.3", "Edgar", "Apt.4", "Apt.7", "Pamela", "Giusy", "Cristina", "John"]
#result: ['Cristian', 'Cristina', 'Edgar', 'John', 'Giusy', 'Pamela', 'Apt.7', 'Apt.3', 'Apt.4']
# write here
List of strings
We said we can put any object into a list, for example some strings:
[41]:
vegetables = ['tomatoes', 'onions', 'carrots', 'cabbage']
Let’s try extracting a vegetable by writing this expression:
[42]:
vegetables[2]
[42]:
'carrots'
Now, the preceding expression produces the result 'carrots'
, which we know is a string. This suggests we can use the expression exactly like if it were a string.
Suppose we want to obtain the first character of the string 'carrots'
, if we directly have the string we can write like this:
[43]:
'carrots'[0]
[43]:
'c'
But if the string is inside the previous list, we could directly do like this:
[44]:
vegetables[2][0]
[44]:
'c'
Exercise - province codes
Given a list with exactly 4 province codes in lowercase, write some code which creates a NEW list containing the same codes in uppercase characters.
your code must work with any list of 4 provinces
hint: if you don’t remember the right method, have a look here
Example 1 - given:
provinces = ['tn','mi','to','ro']
your code must print:
['TN', 'MI', 'TO', 'RO']
Example 2 - given:
provinces = ['pa','ge','ve', 'aq']
Your code must print:
['PA', 'GE', 'VE', 'AQ']
[45]:
provinces = ['tn','mi','to','ro']
#provinces = ['pa','ge','ve', 'aq']
# write here
Exercise - games
Given a list games
of exactly 3 strings, write some code which MODIFIES the list so it contains only the first characters of each string.
Your code must work with any list of exactly 3 strings
Example - given:
games = ["Monopoly","RISK","Bingo"]
After executing the code, it must result:
>>> print(games)
["M","R","B"]
[46]:
games = ["Monopoly", "RISK", "Bingo"] # ['M','R','T']
#games = ["Frustration", "Game of the Goose", "Scrabble"] # ['F','G','S']
# write here
Slices
We can extract sequences from lists by using slices. A slice is produced by placing square brackets after the list with inside the starting index (INCLUDED), followed by a colon :
, followed by the end index (EXCLUDED). It works exactly as with strings: in that case the slice produces a new string, in this case it produces a NEW list. Let’s see an example:
[47]:
#0 1 2 3 4 5 6 7 8 9
la = [40,30,90,80,60,10,40,20,50,60]
[48]:
la[3:7]
[48]:
[80, 60, 10, 40]
We extracted a NEW list [80, 60, 10, 40]
from the list la
starting from index 3
INCLUDED until index 7
EXCLUDED. We can see the original list is preserved:
[49]:
la
[49]:
[40, 30, 90, 80, 60, 10, 40, 20, 50, 60]
Let’s verify what happens with Python Tutor, by assigning the new list to a variable lb
:
[50]:
# 0 1 2 3 4 5 6 7 8 9
la = [40,30,90,80,60,10,40,20,50,60]
lb = la[3:7]
jupman.pytut()
[50]:
You will notice a NEW memory region, associated to variable lb
.
Slice - limits
When we operate with slices we must be careful about indeces limits. Let’s see how they behave:
[51]:
#0 1 2 3 4
[50,90,70,80,60][0:3] # from index 0 *included* to 3 *excluded*
[51]:
[50, 90, 70]
[52]:
#0 1 2 3 4
[50,90,70,80,60][0:4] # from index 0 *included* a 4 *excluded*
[52]:
[50, 90, 70, 80]
[53]:
#0 1 2 3 4
[50,90,70,80,60][0:5] # from index 0 *included* to 5 *excluded*
[53]:
[50, 90, 70, 80, 60]
[54]:
#0 1 2 3 4
[50,90,70,80,60][0:6] # if we go beyond the list length Python does not complain
[54]:
[50, 90, 70, 80, 60]
[55]:
#0 1 2 3 4
[50,90,70,80,60][8:12] # Python doesn't complain even if we start from non-existing indeces
[55]:
[]
QUESTION: This expression:
[][3:8]
produces a result (which one?)
produces an error (which one?)
QUESTION: if x
is some list (may also empty), what does this expression do? Can it give an error? Does it return something useful?
x[0:len(x)]
Exercise - The ‘treccia mochena’
As you well know, a wonderful pastry is made in the Mocheni valley in Trentino: the famous ‘treccia mochena’.
At a quick glance, it may look like a braid loaf, between 30 and 60 cm long with inside a mix of ingredients along a marvellous and secret cream.
With your friends Camilla and Giorgio, you bought a treccia divided in a certain number of portions stuffed with walnuts
, bluberries
and red currants
.
treccia = ['w', 'w', 'w', 'w', 'w', 'b', 'b', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c']
walnuts,bluberries,currants = 5,6,4
You like the bluberries, Giorgio likes walnuts and Camilla the red currants.
Write some code to place into variables mine
, giorgio
and camilla
some lists obtained from treccia
, and PRINT the result:
Mine: ['b', 'b', 'b', 'b', 'b', 'b']
Giorgio: ['w', 'w', 'w', 'w', 'w']
Camilla: ['c', 'c', 'c', 'c']
suppose
treccia
has always only 3 ingredientsDO NOT write constant numbers (except
0
)
[56]:
# Walnuts Bluberries Currants
walnuts,bluberries,currants,treccia = 5,6,4,['w', 'w', 'w', 'w', 'w', 'b', 'b', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c']
#walnuts,bluberries,currants,treccia = 2,4,3,['W', 'W', 'B', 'B', 'B', 'B', 'C', 'C', 'C']
# write here
Slices - omitting limits
If we will, it’s possible to omit start index, in which case Python will suppose it’s 0
:
[57]:
#0 1 2 3 4 5 6 7 8 9
[90,60,80,70,60,90,60,50,70][:3]
[57]:
[90, 60, 80]
It’s also possible to omit the end index, in this case Python will extract elements until the list end:
[58]:
#0 1 2 3 4 5 6 7 8 9
[90,60,80,70,60,90,60,50,70][3:]
[58]:
[70, 60, 90, 60, 50, 70]
By omitting both indexes we obtain the full list:
[59]:
#0 1 2 3 4 5 6 7 8 9
[90,60,80,70,60,90,60,50,70][:]
[59]:
[90, 60, 80, 70, 60, 90, 60, 50, 70]
QUESTION: What is this code going to print? Will la
get modified or not?
la = [7,8,9]
lb = la[:]
lb[0] = 6
print('la =',la)
print('lb =',lb)
[60]:
la = [7,8,9]
lb = la[:]
lb[0] = 6
#print('la =',la)
#print('lb =',lb)
jupman.pytut()
[60]:
QUESTION: For each of the following expressions, try guessing which value it produces, or if it gives an error.
[9,7,8,6][1:1]
[9,7,8,6][1:2]
[9,7,8,6][2:3][0]
[][]
[][:]
[3][:]
[:][]
Exercise - An out of tune guitar
In the attic you found an old guitar which was around when you were a child. Now that you have a degree in Sound Engineering you try playing it while a sensor measures the notes it produces.
The sensor is a microphone, and each one tenth of second it records the main note it detected.
You discover this phenomena: when played, some guitar strings have an oscillating behaviour, but then they synthonize on a precise note until the end:
'D', 'A', 'F', 'E', 'B', 'G', 'B', 'F', 'F', 'F', 'F', 'F', 'F', 'F', '...'
Other strings do the opposite:
'C', 'C', 'C', 'C', 'C', 'D', 'G', 'F', 'B', 'B', 'C', 'B', '...'
A list cutoffs
records for each string the instants in which the weird behaviour starts or ends. The instants are represented as a sequence of beats '*'
, for example the first string starts an anomalous behaviour after 5 beats: '*****'
, while the seconds ends the anomalous behaviour after 7 beats: '*******'
Write some code to cut the sensor output and obtain only the sequences of continuous and correct notes. In the end, it should PRINT:
['C', 'C', 'C', 'C', 'C']
['F', 'F', 'F', 'F', 'F', 'F', 'F', '...']
['D', 'D', 'D', 'D', 'D', 'D', '...']
['G', 'G', 'G', 'G']
DO NOT write constant numbers of instants in the code, instead, use the variable
cutoffs
[61]:
cutoffs = ['*****',
'*******',
'***',
'****',]
string1 = ['C', 'C', 'C', 'C', 'C', 'D', 'G', 'F', 'B', 'B', 'C', 'B', '...']
string2 = ['D', 'A', 'F', 'E', 'B', 'G', 'B', 'F', 'F', 'F', 'F', 'F', 'F', 'F', '...']
string3 = ['B', 'E', 'G', 'D', 'D', 'D', 'D', 'D', 'D', '...']
string4 = ['G', 'G', 'G', 'G', 'D', 'D', 'A', 'A', 'B', 'F', 'B', '...']
# write here
Slices - negative limits
It’s also possible to set inverse and negative limits, although it’s not always intuitive:
[62]:
#0 1 2 3 4 5 6
[70,40,10,50,60,10,90][3:0] # from index 3 to positive indexes <= 3 produces nothing
[62]:
[]
[63]:
#0 1 2 3 4 5 6
[70,40,10,50,60,10,90][3:1] # from index 3 to positive indexes <= 3 produces nothing
[63]:
[]
[64]:
#0 1 2 3 4 5 6
[70,40,10,50,60,10,90][3:2] # from index 3 to positive indexes <= 3 produces nothing
[64]:
[]
[65]:
#0 1 2 3 4 5 6
[70,40,10,50,60,10,90][3:3] # from index 3 to positive indexes <= 3 produces nothing
[65]:
[]
Let’s see what happens with negative indexes:
[66]:
# 0 1 2 3 4 5 6
#-7 -6 -5 -4 -3 -2 -1
[70,40,10,50,60,10,90][3:-1]
[66]:
[50, 60, 10]
[67]:
# 0 1 2 3 4 5 6
#-7 -6 -5 -4 -3 -2 -1
[70,40,10,50,60,10,90][3:-2]
[67]:
[50, 60]
[68]:
# 0 1 2 3 4 5 6
#-7 -6 -5 -4 -3 -2 -1
[70,40,10,50,60,10,90][3:-3]
[68]:
[50]
[69]:
# 0 1 2 3 4 5 6
#-7 -6 -5 -4 -3 -2 -1
[70,40,10,50,60,10,90][3:-4]
[69]:
[]
[70]:
# 0 1 2 3 4 5 6
#-7 -6 -5 -4 -3 -2 -1
[70,40,10,50,60,10,90][3:-5]
[70]:
[]
It’s also possible to start from a negative index and arrive to a positive one. As long as the first index marks a position which precedes the second index, something gets returned:
[71]:
# 0 1 2 3 4 5 6
#-7 -6 -5 -4 -3 -2 -1
[70,40,10,50,60,10,90][-7:3]
[71]:
[70, 40, 10]
[72]:
# 0 1 2 3 4 5 6
#-7 -6 -5 -4 -3 -2 -1
[70,40,10,50,60,10,90][-6:3]
[72]:
[40, 10]
[73]:
# 0 1 2 3 4 5 6
#-7 -6 -5 -4 -3 -2 -1
[70,40,10,50,60,10,90][-5:3]
[73]:
[10]
[74]:
# 0 1 2 3 4 5 6
#-7 -6 -5 -4 -3 -2 -1
[70,40,10,50,60,10,90][-4:3]
[74]:
[]
[75]:
# 0 1 2 3 4 5 6
#-7 -6 -5 -4 -3 -2 -1
[70,40,10,50,60,10,90][-3:3]
[75]:
[]
[76]:
# 0 1 2 3 4 5 6
#-7 -6 -5 -4 -3 -2 -1
[70,40,10,50,60,10,90][-2:3]
[76]:
[]
QUESTION: For each of the following expressions, try guessing which value is produced, or if it gives an error
[9,7,8,6][0:-2]
[0:-2][9,7,8,6]
[5,7,9][1:-1]
[][-13:-17]
[9,7,8,6][-4:-1]
[9,7,8,6][-5:-1]
[9,7,8,6,10,32][-3:1]
[9,7,8,6,10,32][-3:5]
Exercise - The NonsenShop
To keep your expenses under control you want to write a software which tracks everything you buy, and reduce pointless expenses.
You just need to take a picture of the receit with the smartphone, and an OCR (Optical Character Recognition) module will automatically read the text.
all receits have the same schema: shop name, date, “Bought items”, 1 row per item, total, thanks.
assume all the receits are always ordered by price
Write some code to create a NEW list with only the items rows, for example:
['Green varnish for salad 1,12€',
'Anti-wind lead confetti 4,99€',
'Comb for pythons 12,00€',
'Cigarette lighter for diving 23,00€',
'Transparent home shoes 35,56€']
Print the most expensive item like this:
Most expensive item was: Transparent home shoes
cost: 35,56€
[77]:
receit = ["NonsenShop",
"July 21, 2021 14:54",
"Items:",
"Green varnish for salad 1,12€",
"Anti-wind lead confetti 4,99€",
"Comb for pythons 12,00€",
"Cigarette lighter for diving 23,00€",
"Transparent home shoes 35,56€",
"Total 56,66€",
"Thanks for buying our nonsense!"]
#receit = ["Eleganz",
# "January 3 2020 12:53",
# "Items:",
# "Wedge heels with acquarium and fishes 342,00€",
# "'Elvis' suit 20.000,00€",
# "Total 20.000,342€",
# "And now unleash the party animal in you!"]
# write here
Slice - step
It’s also possible to specify a third parameter called ‘step’ to tell Python how many cells to skip at each read. For example, here we start from index 3 and arrive to index 9 excluded, skipping by 2:
[78]:
# 0 1 2 3 4 5 6 7 8 9
[ 0,10,20,30,40,50,60,70,80,90][3:9:2]
[78]:
[30, 50, 70]
All the sequence, skipping by 3:
[79]:
# 0 1 2 3 4 5 6 7 8 9
[ 0,10,20,30,40,50,60,70,80,90][0:10:3]
[79]:
[0, 30, 60, 90]
We can also omit the limits to obtain the equivalent expression:
[80]:
# 0 1 2 3 4 5 6 7 8 9
[ 0,10,20,30,40,50,60,70,80,90][::3]
[80]:
[0, 30, 60, 90]
Slices - modifying
Suppose we have the list
[81]:
#0 1 2 3 4 5 6 7
la = [30,40,80,10,70,60,40,20]
and we want to change la
cells from index 3
INCLUDED to index 6
EXCLUDED in such a way they contain the numbers taken from list [91,92,93]
. We can do it with this special notation which allows us to write a slice to the left of operator =
:
[82]:
la[3:6] = [91,92,93]
[83]:
la
[83]:
[30, 40, 80, 91, 92, 93, 40, 20]
In this slightly more complex example we verify in Python Tutor that the original memory region gets actually modifyied:
[84]:
# 0 1 2 3 4 5 6 7
la = [30,40,80,10,70,60,40,20]
lb = la
lb[3:6] = [91,92,93]
jupman.pytut()
[84]:
QUESTION: Look at the following code - what does it produce?
la = [9,6,5,8,2]
la[1:4] = [4,7,0]
print(la)
modify
la
(how?)an error (which one?)
QUESTION: Look at the following code. What does it produce?
la = [7,6,8,4,2,4,2,3,1]
i = 3
lb = la[0:i]
la[i:2*i] = lb
print(la)
modifies
la
(how?)an error (which one?)
Exercise - The railway outlaws
United States - May 13th, 1857
The colonization of the West is a hard job but somebody gotta do it. Mountains are stuffed with rare minerals and cute animals to be transformed into precious fur coats for noblewomans of Europe. As always, with great wealth come great outlaws.
You are the station master of Denver and you must manage the trains. There are three main lines, Colorado Springs, Fort Collins e New York:
from Colorado Springs always arrive exactly 1 wagon of coal, 3 of minerals and 3 of passengers alternated.
from Fort Collins always arrive exactly 2 wagons of coal, 2 of passengers and 2 of cattle
When trains reach Denver, their content is transfered into the empty wagons of the New York train like this:
to prevent robberies, all the precious wagons are to be positioned nearby the locomotive
the cattle is to be placed always behind passengers, because as much as hygiene in the west is lacking, it’s still easier to pretend humans bathe more than cattle
Write some code which MODIFIES the ORIGINAL memory region of new_york
list by copying the strings from colorado
and fort
MINIMIZE the number of assignments! (the best solution with just slices has only has three assignments!)
DO NOT write constant strings in your code (so no
"cowboy"
,"gold"
, …)
Example - given:
[85]:
colorado = ["CS locomotive","coal", "cowboy", "gold","miners", "gold","cowboy","silver"]
fort = ["FC locomotive","coal", "coal", "gentlmen","ladies", "cows","horses"]
new_york = ["NY locomotive","coal", "", "", "", "", "", "", "","",""]
after your code it must result:
>>> print(new_york)
['NY locomotive', 'coal', 'gold', 'gold', 'silver', 'cowboy', 'miners', 'cowboy', 'gentlmen', 'ladies', 'cows', 'horses']
[86]:
# 0 1 2 3 4 5 6 7 8 9 10
colorado = ["CS locomotive","coal", "cowboy", "gold","miners", "gold","cowboy","silver"]
fort = ["FC locomotive","coal", "coal", "gentlmen","ladies", "cows","horses"]
new_york = ["NY locomotive","coal", "", "", "", "", "", "", "","",""]
# write here
List of lists
NOTE: We will talk much more in detail of lists of lists in the tutorial Matrices - list of lists, this is just a brief introduction.
The consideration we’ve seen so far about string lists are also valid for a list of lists:
[88]:
couples = [ # external list
[67,95], # internal list at index 0
[60,59], # index 1
[86,75], # index 2
[96,90], # index 3
[88,87], # index 4
]
If we want ot extract the number 90
, we must first extract the sublist from index 3
:
[89]:
couples[3] # NOTE: the expression result is a list
[89]:
[96, 90]
and so in the extracted sublist (which has only two elements) we can recover the number at index 0
:
[90]:
couples[3][0]
[90]:
96
and at index 1
:
[91]:
couples[3][1]
[91]:
90
Exercise - couples
Write some code to extract and print the numbers
86
,67
and87
Given a row with index
i
and a columnj
, print the number at rowi
and columnj
multiplied by the number at successive row and same column
After your code, you should see printed
1) 86 67 87
2) i = 3 j = 1 result = 7830
[92]:
couples = [ # external list
[67,95], # internal list at index 0
[60,59], # internal list at index 1
[86,75], # internal list at index 2
[96,90], # internal list at index 3
[88,87], # internal list at index 4
]
i = 3
j = 1
# write here
Exercise - Glory to Gladiators!
The gladiators fight for the glory of the battle and the entertainment of the Emperor and the people! Sadly, not all gladiators manage to fight the same number of battles..
For each fight, each gladiator receives a reward in sesterces (in case he doesn’t survive, it will be offered to his patron…)
At the end of the games, the Emperor throws the prize in sesterces to his favourite gladiator. The Emperor has bad aim and his weak arms don’t allow him to throw everything at once, so he always ends up throwing half of the money to the chosen gladiator and half to the next gladiator.
NOTE: the Emperor never chooses the last of the list
Given a prize
and gladiators
list of sublists of arbitrary length, and a gladiator at index i
, write some code which MODIFIES the sublists of gladiators
at row i
and following one so to increase the last element of both lists of half prize
.
Your code must work with any
prize
,gladiators
andi
Example - given:
and given:
prize, i = 40, 1
after your code, by writing (we use pprint
so printing happens on many lines) it must result:
>>> from pprint import pprint
>>> pprint(gladiatori,width=30)
[[67, 95],
[60, 23, 23, 13, 79],
[86, 95],
[96, 90, 92],
[88, 87]]
[93]:
prize, i = 40, 1 # sesterces, gladiator to award
#prize, i = 10, 3
gladiators = [ # external list
[67,95], # internal list at index 0
[60,23,23,13,59], # internal list at index 1
[86,75], # internal list at index 2
[96,90,92], # internal list at index 3
[88,87], # internal list at index 4
]
# write here
Membership
To verify whether an object is contained in a list, we can use the in
operator.
Note the result of this expression is a boolean:
[94]:
9 in [6,8,9,7]
[94]:
True
[95]:
5 in [6,8,9,7]
[95]:
False
[96]:
"apple" in ["watermelon","apple","banana"]
[96]:
True
[97]:
"carrot" in ["watermelon","apple","banana"]
[97]:
False
Do not abuse in
WARNING: in
is often used in a wrong / inefficient way
Always ask yourself:
Could the list not contain the substring we’re looking for? Always remember to also handle his case!
in
performs a search on all the list, which might be inefficient: is it really necessary, or we already know the interval where to search?If we wanted to know whether
element
is in a position we know a priori (i.e.3
),in
is not needed, it’s enough to writemy_list[3] == element
. By usingin
Python might find duplicated elements which are before or after the one we want to verify!
QUESTION: What’s the result of this expression? True
or False
?
True in [ 5 in [6,7,5],
2 in [8,1]
]
not in
We can write the check of non belonging in two ways:
Way 1:
[98]:
"carrot" not in ["watermelon","banana","apple"]
[98]:
True
[99]:
"watermelon" not in ["watermelon","banana","apple"]
[99]:
False
Way 2:
[100]:
not "carrot" in ["watermelon","banana","apple"]
[100]:
True
[101]:
not "watermelon" in ["watermelon","banana","apple"]
[101]:
False
QUESTION: Given any element x
and list y
, what does the following expression produce?
x in y and not x in y
False
True
False
orTrue
according to the values ofx
andy
an error
QUESTION: For each of the following expressions, try to guess the result
3 in [3]
[4,5] in [1,2,3,4,5]
[4,5] in [[1,2,3],[4,5]]
[4,5] in [[1,2,3,4],[5,6]]
'n' in ['alien'[-1]]
'rts' in 'karts'[1:4]
[] in [[[]]]
[] in [[]]
[] in ["[]"]
QUESTION: For each of the following expressions, independently from the value of x
and y
, tell whether it always results True
:
x in x
x in [x]
x not in []
x in [[x]]
x in [[x][0]]
(x and y) in [x,y]
x in [x,y] and y in [x,y]
Exercise - vegetables
Given the list vegetables
of exactly 5 strings and the list of strings fruits
, MODIFY the variable vegetables
so that in each cell there is True
if the vegetable is a fruit or False
otherwise.
your code must work with any list of 5 strings
vegetables
and any listfruits
Example - given:
vegetables = ["carrot",
"cabbage",
"apple",
"aubergine",
"watermelon"]
fruits = ["watermelon","banana","apple",]
after execution your code must print:
>>> print(vegetables)
[False, False, True, False, True]
[102]:
vegetables = ["carrot",
"cabbage",
"apple",
"aubergine",
"watermelon"]
fruits = ["watermelon","banana","apple",]
# write here
List concatenation with +
Given two lists la
and lb
, we can concatenate them with the operator +
which produces a NEW list:
[103]:
la = [70,60,80]
lb = [90,50]
la + lb
[103]:
[70, 60, 80, 90, 50]
Note the operator +
produces a NEW list, so la
and lb
remained unchanged:
[104]:
print(la)
[70, 60, 80]
[105]:
print(lb)
[90, 50]
Let’s check with Python Tutor:
[106]:
la = [70,60,80]
lb = [90,50]
lc = la + lb
print(la)
print(lb)
print(lc)
jupman.pytut()
[70, 60, 80]
[90, 50]
[70, 60, 80, 90, 50]
[106]:
Exercise - concatenation
Write some code which given lists la
and lb
, puts into list lc
the last two elements of la
and the first two of lb
Example - given:
la = [18,26,30,45,55]
lb = [16,26,37,45]
after your code it must print:
>>> print(la)
[18, 26, 30, 45, 55]
>>> print(lb)
[16, 26, 37, 45]
>>> print(lc)
[45, 55, 16, 26]
[107]:
la = [18,26,30,45,55]
lb = [16,26,37,45]
# write here
QUESTION: For each of the following expressions, try guessing the result
[6,7,8] + [9]
[6,7,8] + []
[] + [6,7,8]
[] + []
[] + [[]]
[[]]+[]
[[]]+[[]]
([6] + [8])[0]
([6] + [8])[1]
([6] + [8])[2:]
len([4,2,5])+len([3,1,2])
len([4,2,5] + [3,1,2])
[5,4,3] + "3,1"
[5,4,3] + "[3,1]"
"[5,4,3]" + "[3,1]"
["4","1","7"] + ["3","1"]
list('coca') + ['c','o','l','a']
min and max
A list is a sequence of elements, and as such we can pass it to functions min
or max
for finding respectively the minimum or the maximum element of the list.
[108]:
min([4,5,3,7,8,6])
[108]:
3
[109]:
max([4,5,3,7,8,6])
[109]:
8
V COMMANDMENT : You shall never ever use min
and max
as variable names
If you do, you will lose the functions!
Note it’s also possible to directly pass to min
and max
the elements to compare without including them in a list:
[110]:
min(4,5,3,7,8,6)
[110]:
3
[111]:
max(4,5,3,7,8,6)
[111]:
8
But if we pass only one, without including it in a list, we will get an error:
min(4)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-156-bb3db472b52e> in <module>
----> 1 min(4)
TypeError: 'int' object is not iterable
The error tells us that when we pass only an argument, Python expects a sequence like a list:
[112]:
min([4])
[112]:
4
To min
and max
we can also pass strings, and we will get the character which is alphabetically lesser or greater:
[113]:
min("orchestra")
[113]:
'a'
[114]:
max("orchestra")
[114]:
't'
If we pass a list of strings, we will obtain the lesser or greater string in lexicographical order (i.e. the phonebook order)
[115]:
min(['the', 'sailor', 'walks', 'around', 'the', 'docks'])
[115]:
'around'
[116]:
max(['the', 'sailor', 'walks', 'around', 'the', 'docks'])
[116]:
'walks'
QUESTION: For each of the following expressions, try guessing the result (or if it gives an error)
max(7)
max([7])
max([5,4,6,2])
max([min([7,3])])
max([])
max(2,9,3)
max([3,2,5] + [9,2,3])
max(max([3,2,5], max([9,2,3]))
max(min(3,6), min(8,2))
min(max(3,6), max(8,2))
max(['a','b','d','c'])
max(['boat', 'dice', 'aloha', 'circle'])
min(['void','','null','nada'])
max(['hammer'[-1],'socket'[-1],'wrench'[-1]])
min(['hammer'[-1],'socket'[-1],'wrench'[-1]])
sum
With sum
we can sum all the elements in a list:
[117]:
sum([1,2,3])
[117]:
6
[118]:
sum([1.0, 2.0, 0.14])
[118]:
3.14
WARNING: DO NOT use sum
as variable name!
If you do, you will lose the function with very bad consequences!
QUESTION: For each of the following expressions, try guessing the result (or if it gives an error):
sum[3,1,2]
sum(1,2,3)
la = [1,2,3] sum(la) > max(la)
la = [1,2,3] sum(la) > max(la)*len(la)
la = [4,2,6,4,7] lb = [max(la), min(la), max(la)] print(max(lb) != max(la))
Exercise - balance
Given a list of n
numbers balance
with n
even, write some code which prints True
if the sum of all first n/2
numbers is equal to the sum of all successive ones.
your code must work for any number list
Example 1 - given:
balance = [4,3,7,1,5,8]
after your code, it must print:
True
Example 2 - given:
balance = [4,3,3,1,9,8]
after your code, it must print:
False
[119]:
balance = [4,3,7,1,5,8]
#balance = [4,3,3,1,9,8]
# write here
List replication
To replicate the elements of a list, it’s possible to use the operator *
which produces a NEW list:
[120]:
[7,6,8] * 2
[120]:
[7, 6, 8, 7, 6, 8]
[121]:
[7,6,8] * 3
[121]:
[7, 6, 8, 7, 6, 8, 7, 6, 8]
Note a NEW list is produced, and the original one is not modified:
[122]:
la = [7,6,8]
[123]:
lb = [7,6,8] * 3
[124]:
la # original
[124]:
[7, 6, 8]
[125]:
lb # expression result
[125]:
[7, 6, 8, 7, 6, 8, 7, 6, 8]
We can multiply a list of strings:
[126]:
la = ["a", "world", "of", "words"]
[127]:
lb = la * 2
[128]:
print(la)
['a', 'world', 'of', 'words']
[129]:
print(lb)
['a', 'world', 'of', 'words', 'a', 'world', 'of', 'words']
As long as we multiply lists which contain immutable elements like numbers or strings, no particular problems arise:
[130]:
la = ["a", "world", "of", "words"]
lb = la * 2
jupman.pytut()
[130]:
The matter becomes much more sophisticated when we multiply lists which contain mutable objects like other lists. Let’s see an example:
[131]:
la = [5,6]
lb = [7,8,9]
lc = [la,lb] * 2
[132]:
print(la)
[5, 6]
[133]:
print(lb)
[7, 8, 9]
[134]:
print(lc)
[[5, 6], [7, 8, 9], [5, 6], [7, 8, 9]]
By printing it, we see that the lists la
and lb
are represented inside lc
- but how, exactly? print
calls may trick you about the effective state of memory - to investigate further it’s convenient to use Python Tutor:
[135]:
la = [5,6]
lb = [7,8,9]
lc = [la,lb] * 2
jupman.pytut()
[135]:
Arggh ! A jungle of arrows will appear ! This happens because when we write [la, lb]
we create a list with two references to other lists [5,6]
and [7,8,9]
, and the operator *
when duplicating it just copies references.
For now we stop here, we will see the implications details later in the tutorial matrices - lists of lists
Equality
We can check whether two lists are equal with equality operator ==
, which given two lists returns True
if they contain equal elements or False
otherwise:
[136]:
[4,3,6] == [4,3,6]
[136]:
True
[137]:
[4,3,6] == [4,3]
[137]:
False
[138]:
[4,3,6] == [4,3,6, 'ciao']
[138]:
False
[139]:
[4,3,6] == [2,2,8]
[139]:
False
We can check equality of lists with heterogenous elements:
[140]:
['apples', 3, ['cherries', 2], 6] == ['apples', 3, ['cherries', 2], 6]
[140]:
True
[141]:
['bananas', 3,['cherries', 2], 6] == ['apples', 3, ['cherries', 2], 6]
[141]:
False
To check for inequality, we can use the operatpr !=
:
[142]:
[2,2,8] != [2,2,8]
[142]:
False
[143]:
[4,6,0] != [2,2,8]
[143]:
True
[144]:
[4,6,0] != [4,6,0,2]
[144]:
True
QUESTION: For each of the following expressions, guess whether it is True
, False
or it produces an error:
[2,3,1] != [2,3,1]
[4,8,12] == [2*2,4*2,6*2]
[7,8][:] == [7,9-1]
[7][0] == [[7]][0]
[9] == [9][0]
[max(7,9)] == [max([7]),max([9])]
['a','b','c'] == ['A','B','C']
['a','b'] != ['a','b','c']
["ciao"] != ["CIAO".lower()]
[True in [True]] != [False]
[][:] == []
[[]] == [] + []
[[],[]] == [] + []
[[[]]] == [[[]+[]]]
Continue
You can find more exercise in the notebook Lists 3 - basic methods
[ ]: