Osa 4

Silmukat ja iterointi

Voimme käydä listan alkiot läpi while-silmukalla samaan tapaan kuin olemme aiemmin käyneet läpi merkkijonon merkkejä. Esimerkiksi seuraava ohjelma tulostaa kaikki listan alkiot omille riveilleen:

lista = [3, 2, 4, 5, 2]

kohta = 0
while kohta < len(lista):
    print(lista[kohta])
    kohta += 1
Esimerkkitulostus

3 2 4 5 2

Tämä on kuitenkin melko vaivalloinen tapa, sillä joudumme käyttämään indeksimuuttujaa kohta, joka "muistaa", missä kohtaa listaa ollaan menossa. Nyt on aika opetella parempi tapa listan, merkkijonon tai muun vastaavan rakenteen läpikäyntiin.

for-silmukka

Pythonin for-silmukka käy läpi annetun rakenteen sisällön. Esimerkiksi voimme käydä läpi kaikki listalla olevat alkiot vasemmalta oikealle. Ohjelmoinnissa tällaista läpikäyntiä kutsutaan myös nimellä iterointi.

Ideana on, että for-silmukka poimii yksi kerrallaan kunkin alkion ja suorittaa kaikille saman operaation. Näin ohjelmoijan ei tarvitse itse huolehtia, mistä kohdasta alkio haetaan missäkin vaiheessa. Silmukan syntaksi on seuraava:

for <muuttuja> in <rakenne>:
    <lohko>

Kun for-silmukka käy listan läpi, se poimii vuorollaan kunkin alkion, sijoittaa sen muuttujaan ja suorittaa lohkon. Kun silmukka on käynyt kaikki alkiot läpi, ohjelman suoritus jatkuu silmukan jälkeiseltä riviltä.

Listan iterointi

Seuraava ohjelma tulostaa listan kaikki alkiot for-silmukan avulla:

lista = [3, 2, 4, 5, 2]

for alkio in lista:
    print(alkio)
Esimerkkitulostus

3 2 4 5 2

Jos verrataan tätä edelliseen esimerkkiin, huomataan, että for-silmukka selkeyttää suoraviivaista listan alkioiden läpikäyntiä huomattavasti.

Voimme käydä samalla idealla läpi myös merkkijonon merkit:

nimi = input("Anna nimesi: ")

for merkki in nimi:
    print(merkki)
Esimerkkitulostus

Anna nimesi: Pekka P e k k a

Loading

Funktio range

Silmukkaa tarvitaan usein myös siihen, että haluamme toistaa jonkin asian tietyn määrän kertoja tai käydä läpi tietyn lukuvälin (esimerkiksi kaikki luvut väliltä 1–100). Myös tämä onnistuu kätevästi for-silmukalla funktion range avulla.

Voimme kutsua range-funktiota monella tavalla. Yksinkertaisin tapa on range(n), jolloin silmukka käy läpi kokonaisluvut 0:sta lukuun n–1:

for i in range(5):
    print(i)
Esimerkkitulostus

0 1 2 3 4

Kun annamme kaksi parametria, range(a, b) aloittaa luvusta a ja lopettaa lukuun b–1:

for i in range(3, 7):
    print(i)
Esimerkkitulostus

3 4 5 6

Kun annamme kolme parametria, range(a, b, c) aloittaa luvusta a, lopettaa lukuun b–1 ja muuttaa lukua c:llä joka askeleella:

for i in range(1, 9, 2):
    print(i)
Esimerkkitulostus

1 3 5 7

Voimme myös antaa negatiivisen askeleen, jolloin luvut käydään läpi käänteisesti:

for i in range(6, 2, -1):
    print(i)
Esimerkkitulostus

6 5 4 3

Loading

Lukuväli listaksi

Funktio range palauttaa lukuvälin, joka voidaan käydä läpi listan kaltaisesti mutta joka ei kuitenkaan ole lista. Tämän näkee siitä, että jos tulostamme funktion palauttaman arvon, näemme vain kuvauksen lukuvälistä:

luvut = range(2, 7)
print(luvut)
Esimerkkitulostus

range(2, 7)

Tutustumme asiaan tarkemmin Ohjelmoinnin jatkokurssilla, mutta on hyvä tietää, että voimme muuttaa lukuvälin listaksi funktiolla list. Tällöin listaan tulevat kaikki lukuväliin kuuluvat arvot:

luvut = list(range(2, 7))
print(luvut)
Esimerkkitulostus

[2, 3, 4, 5, 6]

Muistutus tehtävien funktioita testaavasta omasta koodista

Funktiotehtävien tehtäväpohjat ovat tähän asti näyttäneet seuraavilta:

# tee ratkaisu tänne
# funktiota kannattaa testata kutsumalla sitä täällä seuraavasti
if __name__ == "__main__":
    lause = "olipa kerran kauan sitten ohjelmoija"
    print(eka_sana(lause))
    print(toka_sana(lause))
    print(vika_sana(lause))

Tästä eteenpäin muistutusta siitä, että testikoodi on sijoitettava if __name__ == "__main__" -lohkoon, ei tehtäväpohjissa enää ole. Testit kuitenkin vaativat lohkon edelleen, eli joudut lisäämään sen itse.

Huomaa kuitenkin, että jotkut tehtävät, esim. hetken kuluttua vuorossa oleva Palindromit, edellyttävät funktioiden lisäksi myös funktiota kutsuvaa koodia. Tätä koodia ei tule sijoittaa if __name__ == "__main__" -lohkon sisälle. Testit eivät nimittäin suorita mitään kyseisen lohkon koodista.

Loading
Loading
Loading
Loading

Kertaa nyt tarvittaessa edellisen osion luku Lista funktion parametrina ja paluuarvona!

Loading
Loading
Loading

Parhaan tai huonoimman etsiminen listalta

Ohjelmoinnissa tulee usein esiin tilanne, missä listalta on löydettävä jonkin kriteerin mukaan paras tai huonoin alkio. Ratkaisu onnistuu käyttämällä sopivaa apumuuttujaa, jonka avulla voidaan "muistaa" läpikäynnin aikana siihen mennessä löytynyt paras alkio. Tätä muistettavaa alkiota verrataan sitten yksi kerrallaan jokaiseen vastaantulevaan alkioon, ja lopulta on tiedossa koko listan paras.

Algoritmin "luonnos" on seuraavassa:

paras = alkuarvo # sopiva alkuarvo riippuu tilanteesta
for alkio in lista:
    if alkio parempi kuin paras:
        paras = alkio

# paras on nyt tiedossa!

Koodin yksityiskohdat riippuvat siitä minkä tyyppisiä alkioita listalla on ja mikä parhauden/huonouden vertailukriteeri on käytössä. Joissain tilanteissa myös apumuuttujia saatetaan tarvita useampia.

Harjoitellaan hieman tämän ratkaisumenetelmän käyttöä.

Loading
Loading
Loading
Loading...
:
Loading...

Log in to view the quiz