List comprehensions#
Verdubbel alle waarden in een lijst
l = [4, 5, 6]
for i in range(0, len(l)):
l[i] = l[i] * 2
print(l)
[8, 10, 12]
Het komt vaak voor dat we een bewerking willen uitvoeren op alle elementen in een lijst. Python geeft de optie omdat in het kort op te schrijven: een list comprehension.
l = [4, 5, 6]
l = [x * 2 for x in l]
print(l)
[8, 10, 12]
Dit werkt ook met de index versie van een for lus.
l = [4, 5, 6]
l = [l[i] * 2 for i in range(0, len(l))]
print(l)
[8, 10, 12]
Naast berekening kunnen we ook een functie uitvoeren op alle elementen in een lijst.
def dbl(x):
"""Verdubbel een getal
"""
return x * 2
l = [4, 5, 6]
l = [dbl(x) for x in l]
print(l)
[8, 10, 12]
Soms komt het voor dat we alleen de elementen willen bewerken en toevoegen aan een nieuwe lijst als het aan een bepaalde voorwaarde voldoet. Dit kunnen we doen door een if-statement toe te voegen aan de list comprehension.
We kunnen bijvoorbeeld alle oneven getallen uit een list filteren.
l = [1, 2, 3, 4, 5, 6]
l = [x for x in l if x % 2 == 1]
print(l)
[1, 3, 5]
Miljoen keer simuleren#
import sys
from random import *
def guess_np(hidden):
"""Raad een getal
hidden: het te raden getal
"""
guesses = 0
while True:
comp_guess = choice(range(100)) # 0 tot en met 99.
guesses += 1
if comp_guess == hidden:
break
return guesses
print(guess_np(42))
44
De functie geeft het aantal keer dat nodig is om een om een getal te raden terug op basis van steeds een random keus van de computer.
Combineren#
[ expressie voor elke waarde in collectie ]
LC = [guess_np(42) for x in range(1000)]
EĂ©n enkele regel voor het uitvoeren van 1000 simulaties, dat is best indrukwekkend!
Bedenk dat je niet verplicht bent de waarde x
in een expressie te gebruiken. In dit geval is x
een nutteloze variabele die je alleen maar nodig hebt omdat de syntax jou dit verplicht. Vaak zal je zien dat in dit soort gevallen _
wordt gebruikt om aan te geven dat het een “wegwerp” variabele is, bijvoorbeeld in ons geval
[guess_np(42) for _ in range(1000)]
LC[0:10]
[78, 191, 66, 6, 106, 46, 262, 13, 134, 227]
List slicing ken je nu ook en dit komt in dit geval goed van pas om eerste de 10 elementen (het resultaat van de eerste 10 simulaties) te inspecteren.
print("Gemiddeld aantal keer raden", sum(LC) / len(LC))
Gemiddeld aantal keer raden 101.293
Dubbele ogen#
from random import *
def count_doubles(N):
"""Tel aantal dubbele ogen bij N worpen
"""
doubles = 0
for _ in range(0, N):
d1 = choice([1,2,3,4,5,6]) # eerste dobbelsteen
d2 = choice([1,2,3,4,5,6]) # tweede dobbelsteen
if d1 == d2:
doubles += 1
return doubles
print(count_doubles(100))
19
LC = [count_doubles(100) for x in range(1000)]
LC[0:10]
[17, 11, 12, 24, 11, 19, 16, 15, 13, 21]
print("Gemiddeld dubbele ogen (/100):", sum(LC)/len(LC))
Gemiddeld dubbele ogen (/100): 16.734
Condities#
List comprehension met condities
[ expressie voor elke waarde in collectie als <test>]
def vwl(s):
"""Tel het aantal klinkers
"""
LC = [1 for x in s if x in "aeiou"]
return sum(LC)
print(vwl("hanze Hogeschool"))
6
Een ander voorbeeld, tel het aantal elementen in de list L
die gelijk is aan e
.
def count(e, L):
"""Tel het aantal e in L
"""
LC = [1 for x in L if x == e]
return sum(LC)
print(count("o", "hanze Hogeschool"))
3
Oneliners#
def len(L):
LC = [1 for x in L]
return sum(LC)
def len(L):
return sum([1 for x in L])
List comprehesion maakt het mogelijk om met een heel compacte syntax oplossingen te schrijven. Bedenk wel dat dit niet altijd de leesbaarheid ten goede komt en het is geen probleem om het in stukjes uit te schrijven, bijvoorbeeld door het gebruik van een variabele (LC
in de eerste variant).
Opdrachten#
Opdracht 1#
Wat is het resultaat van de volgende list comprehensions
Vraag 1#
[n ** 2 for n in range(0, 5)]
Vraag 2#
[42 for z in [0, 1, 2]]
Vraag 3#
[z for z in [0, 1, 2]]
Vraag 4#
[s[1::2] for s in ["elk", "ook", "vlo"]]
Vraag 5#
[a * (a - 1) for a in range(8) if a % 2 == 1]
Opdracht 2#
Maak de listcomprehension af zodat de functie nodds(L)
voldoet aan de volgende eisen:
input:
L
, een list met getallenoutput: het aantal oneven getallen in
L
Voorbeeld:
nodds([3, 4, 5, 7, 42]) == 3
def nodds(L):
LC = [... for ... in L ...]
return sum(LC)
Cell In[16], line 2
LC = [... for ... in L ...]
^
SyntaxError: invalid syntax. Perhaps you forgot a comma?
Opdracht 3#
Scrabble score#
We gaan een functie schrijven dat de srabble score van een woord kan berekenen.
Gegeven de functie letter_score(s)
dat voor de letter s
de score teruggeeft.
def letter_score(s):
"""Scrabble letter score
"""
if s in "adeinorst":
return 1
elif s in "ghl":
return 2
elif s in "bcmp":
return 3
elif s in "jkuvw":
return 4
elif s == "f":
return 5
elif s == "z":
return 6
elif s in "xy":
return 8
elif s == "q":
return 10
else:
return 0
Maak de listcomprehension af in de onderstaande functie Scrabble_score(s)
dat de score van de string S
kan uitrekenen. Je mag ervan uitgaan dat S
enkel bestaat uit kleine letters.
def scrabble_score(S):
LC = [... for ... in ...] #
return sum(LC)
Opdracht 4#
Maak de listcomprehension af zodat de functie ndivs(N)
voldoet aan de volgende eisen:
input:
N
, een integer >= 2output: het aantal positieve delers van
N
Voorbeeld:
ndivs(12) == 6
(de positieve delers van 12 zijn [1, 2, 3, 4, 6, 12]
)
Tip: gebruik range
om een reeks getallen van 1 tot en met N
te genereren
def ndivs(N):
LC = [... for ... in ... if ...]
return sum(LC)
Opdracht 5#
Een uitdaging!
Maak de listcomprehension af zodat de functie primes_up_to(N)
voldoet aan de volgende eisen:
input:
P
een integer >= 2output: de lijst van priemgetallen tot en met
P
Voorbeeld:
primes_up_to(12) == [2, 3, 5, 7, 11]
Ter herinnering, een priemgetal is een heel getal dat precies door twee getallen kan worden gedeeld en waarmee je met de deling een heel getal overhoudt. Een priemgetal is altijd deelbaar door 1 en deelbaar door zichzelf.
Bijvoorbeeld het getal 5 heeft precies 2 delers, namelijk 1 en 5. Het getal 4 is geen priemgetal, 4 heeft namelijk 3 delers (1, 2 en 4).
def primes_up_to(P):
LC = [... for ... in ... if ...]
return LC
Tip: je kan in de conditie de functie ndivs
gebruiken als in ndivs(x) == 2
.