Listojen läpikäynti (for, zip)

Listan läpikäyminen for-silmukan avulla

Kun meillä on tietoja tallennettuna listaan, haluamme yleensä myös hyödyntää niitä. Tätä varten tarvitsemme menetelmän listojen läpikäyntiin. Seuraava tapa ei olisi kovin kätevä, jos listassa olisi 1000 alkiota:

# Muuntokerroin atm -> bar
ATM_TO_BAR = 1.01325

# Määritellään kolme painetta yksiköissä atm
paineet_atm = [0.56, 1.22, 2.34]
# indeksi:      0      1     2

# Muunnetaan paineet bareiksi brutaalin suoraviivaisesti ja tulostetaan
print(round(paineet_atm[0] * ATM_TO_BAR, 3))
print(round(paineet_atm[1] * ATM_TO_BAR, 3))
print(round(paineet_atm[2] * ATM_TO_BAR, 3))

Luonnollisin tapa listojen läpikäyntiin on for-silmukka (johon tutustuimme 1. kierroksella). Listojen kanssa pääsemme toden teolla hyödyntämään for-silmukoita. 

Esimerkki 1
# Muuntokerroin atm -> bar
ATM_TO_BAR = 1.01325

# Määritellään kolme painetta yksiköissä atm:
paineet_atm = [0.56, 1.22, 2.34]
# indeksi:      0      1     2

# Tulostetaan paineet bareina yksi kerrallaan for-silmukan avulla
for paine_atm in paineet_atm:
    paine_bar = paine_atm * ATM_TO_BAR 
    print(round(paine_bar, 3))

Näin for-silmukan avulla voi käydä läpi helposti listan kaikki alkiot, on niitä sitten 3 tai 3000. Listan läpikäyvän for-silmukan yleinen muoto on siis:

for ALKIO in LISTA:
    print(ALKIO) # silmukassa voimme tehdä alkiolla mitä haluamme
Esimerkki 2

Käydään läpi yhtä listaa ja lisätään samalla alkioita toiseen listaan append-funktiolla (ks. edellinen luku):

# Ratkaistaan paine ideaalikaasun tilanyhtälöstä usealle eri tilavuudelle
n = 0.5 # mol
T = 298.15 # K
R = 8.3144598 # J K^-1 mol^-1

# Määritellään kolme tilavuutta yksiköissä m^3
tilavuudet = [0.010, 0.045, 0.105]

# Luodaan tyhjä lista laskettavia paineita varten
paineet = []
# Lasketaan paineet yksiköissä Pa
for tilavuus in tilavuudet:
    paine = n * R * T / tilavuus
    paineet.append(paine)

# Tulostetaan tilavuudet ja paineet yksinkertaisesti ilman pyöristystä
print("tilavuudet:", tilavuudet)
print("paineet:", paineet)

tulostaa

tilavuudet: [0.01, 0.045, 0.105]
paineet: [123947.80946849998, 27543.957659666663, 11804.553282714285]
Esimerkki 3

Tulostetaan tietoja kahdesta yhtä pitkästä listasta. 

Tehdään suoraviivainen for-silmukka, jossa hyödynnetään silmukkamuuttujaa i.

tilavuudet = [0.01, 0.045, 0.105]
paineet = [123947.80946849998, 27543.957659666663, 11804.553282714285]
# Hyödynnetään silmukkamuuttujaa i ja len-funktiota.
# Silmukkamuuttuja i saa siis arvot range(len(paineet)), eli [0, 1, 2]
for i in range(len(paineet)):
    print("V = {:.3f} m^3; p = {:.0f} Pa".format(tilavuudet[i], paineet[i]))

tulostaa

V = 0.010 m^3; p = 123948 Pa
V = 0.045 m^3; p = 27544 Pa
V = 0.105 m^3; p = 11805 Pa
Esimerkki 4 

Lasketaan arvoja kolmanteen listaan kahden keskenään yhtä pitkän listan avulla:

ainemaarat = [0.4, 0.6, 0.8]    # mol
tilavuudet = [0.25, 0.25, 0.25] # l
konsentraatiot = []             # Lasketaan nämä (mol/l)
for i in range(len(ainemaarat)):
    c = ainemaarat[i] / tilavuudet[i]
    konsentraatiot.append(c)
print(konsentraatiot)

tulostaa

[1.6, 2.4, 3.2]

Ylläolevilla for-silmukoilla kurssin tehtävistä selviää täysin hyväksyttävästi. Seuraavassa kappaleessa on pari vaihtoehtoista tapaa hoitaa sama asia käyttäen Pythonin sisäänrakennettuja hienouksia.

zip-funktio

Kätevä tapa hoitaa esimerkin 4 tilanne on yhdistää kaksi listaa zip-funktion avulla (engl. zip = vetoketju):

ainemaarat = [0.4, 0.6, 0.8]    # mol
tilavuudet = [0.25, 0.25, 0.25] # l
konsentraatiot = []             # Lasketaan nämä (mol/l)
for n, V in zip(ainemaarat, tilavuudet):
    # silmukkamuuttuja n saa arvot listasta ainemaarat
    # silmukkamuuttuja V saa arvot istasta tilavuudet
    c = n / V
    konsentraatiot.append(c)
print(konsentraatiot)

Lopputulos olisi sama kuin edellä. Katsotaan tarkemmin, mitä zip-funktio palauttaa (muuntamalla funktion tulos listaksi):

print(list(zip(ainemaarat, tilavuudet)))

tulostaa

[(0.4, 0.25), (0.6, 0.25), (0.8, 0.25)]

Eli kolmen alkion lista, jossa jokainen alkio on kahden alkion monikko (eli lista, jota ei voi muokata ks. seuraava luku). 

zip-funktio on erittäin kätevä tapa yhdistää listoja for-silmukkaa varten.

enumerate-funktio.

enumerate-funktio on myös usein avuksi listojen läpikäymisessä. Se palauttaa kullekin listan alkiolle sekä sen indeksin että alkion arvon:

alkuaineet = ["H", "He", "Li", "Be"]
for indeksi, alkuaine in enumerate(alkuaineet):
    print("Z: {:d}; alkuaine: {:s}".format(indeksi + 1, alkuaine))

tulostaa

Z: 1; alkuaine: H
Z: 2; alkuaine: He
Z: 3; alkuaine: Li
Z: 4; alkuaine: Be

Saman silmukan voisi toteuttaa myös silmukkamuuttujan avulla:

alkuaineet = ["H", "He", "Li", "Be"]
for i in range(len(alkuaineet)):
    print("Z: {:d}; alkuaine: {:s}".format(i + 1, alkuaineet[i]))

On lähinnä makuasia, kumpaa tapaa käyttää. enumerate-funktio voi auttaa tekemään koodista luettavampaa kuin silmukkamuuttujan käyttö. 

Katsotaan vielä tarkemmin, mitä enumerate-funktio oikeastaan palauttaa (muunnetaan enumerate-funktion tulos listaksi):

alkuaineet = ["H", "He", "Li", "Be"]
print(list(enumerate(alkuaineet)))

tulostaa

[(0, 'H'), (1, 'He'), (2, 'Li'), (3, 'Be')]

Eli kukin alkuaineet-listan alkio on saanut parikseen indeksin. Huomaa, että listassa on neljä alkiota ja jokainen alkio on kahden alkion monikko (lista, jota ei voi muokata ks. seuraava luku).


Lisätietoa: List comprehension -mekanismi

(tämä kappale on syventävää tietoa, ei välttämätöntä kurssin läpäisemiseksi). Kuten ylläolevat esimerkit näyttää, for-silmukka on selkeä työkalu listojen läpikäymiseen ja uusien listojen luomiseen. Mainitsen tässä syventävänä tietona myös List comprehension -mekanismin, jolla Pythonissa on erityisen kätevää luoda uusia listoja olemassaolevien listojen avulla.

List comprehension-lauseke kirjoitetaan hakasulkeiden väliin:

uusi_lista = [ uuden_listan_alkion_lauseke for vanha_alkio in vanha_lista ]

Esimerkki:

tilavuudet_m3 = [0.010, 0.045, 0.105]
tilavuudet_litroina = [ tilavuus_m3 * 1000 for tilavuus_m3 in tilavuudet_m3 ]
print(tilavuudet_m3)
print(tilavuudet_litroina)

tulostaa

[0.01, 0.045, 0.105]
[10.0, 45.0, 105.0]
Toinen esimerkki:

# Ratkaistaan paine ideaalikaasun tilanyhtälöstä usealle eri tilavuudelle
n = 0.5 # mol
T = 298.15 # K
R = 8.3144598 # J K^-1 mol^-1

# Määritellään kolme tilavuutta yksiköissä m^3
tilavuudet = [0.010, 0.045, 0.105]

# Käytetään for-silmukan sijasta "List comprehension"-mekanismia
paineet = [ n * R * T / tilavuus for tilavuus in tilavuudet ]

# Tulostetaan tilavuudet ja paineet yksinkertaisesti ilman pyöristystä
print("tilavuudet:", tilavuudet)
print("paineet:", paineet)


Tehtävä 3.4.1.