(toiminnot)

hwechtla-tl: Listakeräelmien toiminta

Kierre.png

Mikä on WikiWiki?
nettipäiväkirja
koko wiki (etsi)
viime muutokset


Mitä kone varsinaisesti tekee kohdatessaan listakeräelmän? Miten listakeräelmät "suoritetaan"? Listakeräelmien toimintatapa on itse asiassa varsin suoraviivainen, mutta sen hahmottaminen vaatii hieman harjoitusta.

Yleinen sääntö on, että jos haluaa tietää, mitä listakeräelmäilmaus tekee, pitää lukea se alusta loppuun, paitsi että kaikkein ensimmäiseksi sanottu asia (joka on ennen ensimmäistä for-alilausetta) luetaan viimeiseksi. Valaistaanpa tätä asiaa monimutkaistuvin esimerkein.

for-alilauseen toiminta

[paatepysakki(bussilinja) for bussilinja in linjat]

Kone tekee seuraavasti: se käy läpi linjat-listan siten, että muuttuja bussilinja saa arvokseen kunkin linjat-listan elementin vuorollaan. Tämä on keräelmän for-alilauseen merkitys. Jokaista linjat-listan elementtiä kohden se laskee, mikä on kyseisen bussilinjan päätepysäkki. Tämä on keräelmän alkuosan merkitys. Tulokset kerätään uuteen listaan samassa järjestyksessä kuin bussilinjat olivat linjat-listassa. Tämä uusi lista on listakeräelmän tulos.

On tärkeää ymmärtää, että ilmaus paatepysakki(bussilinja) suoritetaan monta kertaa. Se, minkä linjan bussilinja-muuttuja nimeää, vaihtuu joka suorituskerralla. Tällä tavoin perässä oleva for-alilause ohjaa listakeräelmän suorittamista. Mikäli linjat-lista on tyhjä, paatepysakki-funktiota ei kutsuta kertaakaan, ja tuloksena on tyhjä lista.

if-alilauseen toiminta

[paatepysakki(linja) for linja in linjat if ajetaan(linja, 'lauantai')]

Keräelmässä on kolme osaa (alkuosa, for-alilause ja if-alilause), ja ne vaikuttavat suoritukseen tässä järjestyksessä:

  1. for-alilause aiheuttaa sen, että linjat-lista käydään läpi. linja-muuttuja osoittaa vuorotellen kuhunkin linjat-listan elementtiin.
  2. if-alilause aiheuttaa sen, että mikäli linjaa ei ajeta lauantaisin, ei tätä linjaa käsitellä pidemmälle vaan palataan alkuun ja haetaan listan seuraava elementti.
  3. alkuosa aiheuttaa sen, että tuloslistaan kerätään tähän vaiheeseen asti päässeiden linjojen päätepysäkit.

Tuloksena on siis kaikkien lauantaisin ajettavien linjojen päätepysäkit. Tästä huomataan, että for-alilause ohjaa koko toimintaa määräämällä, mille linjoille loput alilauseet ajetaan. if-alilause ohjaa sitä, edetäänkö viimeiseen vaiheeseen eli varsinaiseen keräilyyn.

if-alilauseiden yhdistely

if-alilauseita voi olla listakeräelmässä vaikka kuinka monta:

[linja for linja in linjat
       if operoija(linja) == 'HKL'
       if paatepysakki(linja) == 'Rautatientori']

Luetaan seuraavasti:

  1. for-alilause määrää, mitä käydään läpi (linjat-lista) ja millä nimellä sen elementtejä kutsutaan (linja).
  2. 1. if-alilause rajaa käsiteltävät linjat niihin, joiden operoija on HKL.
  3. 2. if-alilause rajaa jo rajatun joukon edelleen siten, että linjan päätepysäkin on oltava Rautatientori.
  4. alkuosa keräilee linjat sellaisinaan listaan.

Tuloksena on siis lista linjoista, joita ajaa HKL ja joiden päätepysäkki on Rautatientori. Ehdot voisi yhdistää myös yhdeksi if-alilauseeksi (if operoija(linja) == 'HKL' and paatepysakki(linja) == 'Rautatientori').

for-alilauseiden yhdistely

Samoin for-alilauseita voi olla listakeräelmässä vaikka kuinka monta (tosin aina tarvitaan ainakin yksi, joka "virittää" listakeräelmän):

[[kaupunki, linja] for kaupunki in kaupungit for linja in bussilinjat(kaupunki)]

Mitä kone nyt tekee? Luetaan järjestyksessä.

  1. 1. for-alilause käy läpi kaupungit-listan kaupungit siten, että kutakin kaupunkia kutsutaan vuorollaan nimellä kaupunki. Huom! Kaikki seuraava, myös 2. for-alilause, suoritetaan jokaiselle kaupungille erikseen!
  2. 2. for-alilause käy läpi 1. for-alilauseen antaman kaupungin kaikki bussilinjat. Käsittelyssä olevaa linjaa kutsutaan nimellä linja. Huom! Kaikki seuraava tehdään siis jokaisen kaupungin jokaiselle linjalle.
  3. alkuosa kertoo, mitä keräillään. Tässä tapauksessa keräillään 2-kohtaisia listoja, joissa kerrotaan kaupungin ja linjan nimi. Tuloksena on siis lista kaikkien kaupunkien kaikista linjoista.

Tarkastellaan toimintaa vieläkin perusteellisemmin. Olkoot kaupungit = ['Porvoo', 'Pori'], bussilinjat('Porvoo') = [1, 7, 10] ja bussilinjat('Pori') = [1, 2]. Tällöin listakeräelmää suoritettaessa:

  1. kaupunki-muuttuja alkaa osoittaa arvoon 'Porvoo'
  2. tämän perusteella lasketaan bussilinjat(kaupunki) eli [1, 7, 10]
  3. linja-muuttuja alkaa osoittaa arvoon 1
  4. keräillään [kaupunki, linja] eli ['Porvoo', 1]
  5. linja-muuttuja alkaa osoittaa arvoon 7
  6. keräillään [kaupunki, linja] eli ['Porvoo', 7]
  7. linja-muuttuja alkaa osoittaa arvoon 10
  8. keräillään [kaupunki, linja] eli ['Porvoo', 10]
  9. 2. for-alilauseen lista loppuu, palataan 1. for-alilauseeseen
  10. kaupunki-muuttuja alkaa osoittaa arvoon 'Pori'
  11. tämän perusteella lasketaan bussilinjat(kaupunki) eli [1, 2].
  12. linja-muuttuja alkaa osoittaa arvoon 1
  13. keräillään [kaupunki, linja] eli ['Pori', 1]
  14. linja-muuttuja alkaa osoittaa arvoon 2
  15. keräillään [kaupunki, linja] eli ['Pori', 2]
  16. 2. for-alilauseen lista loppuu, palataan 2. for-alilauseeseen
  17. 1. for-alilauseen lista loppuu -> listakeräelmä on valmis

Tuloksena on lista [['Porvoo', 1], ['Porvoo', 7], ['Porvoo', 10], ['Pori', 1], ['Pori', 2]].

for- ja if-alilauseiden yhdistely

for- ja if-alilauseita voi olla sekaisin missä tahansa järjestyksessä (paitsi alussa pitää aina olla yksi for-alilause). Esimerkiksi:

[ydin(tavu) for sana in aineisto
            if mielenkiintoinenko(sana)
            for tavu in tavut(sana)
            if suljettuko(tavu)

Tämä tekee seuraavaa:

  1. käy läpi aineiston (sanojen lista?) siten, että kutakin aineiston osaa kutsutaan nimellä "sana"
  2. rajaa läpikäynnin vain mielenkiintoisiin sanoihin
  3. käy läpi kunkin sanan tavut siten, että kutakin tavua kutsutaan nimellä "tavu"
  4. rajaa läpikäynnin vain niihin tavuihin, jotka ovat suljettuja (eli loppuvat konsonanttiin)
  5. kerää tavuista ytimet (eli vokaaliosan)

Tuloksena on lista, jossa on aineiston mielenkiintoisten sanojen suljettujen tavujen ytimet.

Toisistaan riippumattomat for-alilauseet

Myöhemmän ("sisemmän") for-alilauseen ei tarvitse riippua millään tavoin aiemmasta:

[alku + loppu for alku in ['metsä', 'pelto'] for loppu in ["", 'polku', 'aukea']]

Tässä tapahtuu seuraavaa:

  1. alku-muuttuja saa arvon 'metsä'
  2. loppu-muuttuja saa arvon ""
  3. keräillään alku + loppu eli 'metsä'
  4. loppu-muuttuja saa arvon 'polku'
  5. keräillään alku + loppu eli 'metsäpolku'
  6. loppu-muuttuja saa arvon 'aukea'
  7. keräillään alku + loppu eli 'metsäaukea'
  8. alku-muuttuja saa arvon 'pelto'
  9. loppu-muuttuja saa arvon ""
  10. keräillään alku + loppu eli 'pelto'
  11. loppu-muuttuja saa arvon 'polku'
  12. keräillään alku + loppu eli 'peltopolku'
  13. loppu-muuttuja saa arvon 'aukea'
  14. keräillään alku + loppu eli 'peltoaukea'

Tuloksena on lista ['metsä', 'metsäpolku', 'metsäaukea', 'pelto', 'peltopolku', 'peltoaukea']. Huomionarvoista (ja erilaista aiempiin tapauksiin nähden) on se, että nyt loppu-muuttujan saamat arvot eivät riipu millään tavoin alku-muuttujan saamista arvoista, vaan listakeräelmä käy läpi jokaisen syötelistojen elementtien yhdistelmän.

Tämä eroaa sekä bussi- että tavuesimerkistä: bussiesimerkissä linjat riippuvat vuorossa olevasta kaupungista ja tavuesimerkissä tavut muodostetaan vuorossa olevasta sanasta.


Listakeräelmien käyttö


Pikalinkit:


kommentoi (viimeksi muutettu 11.11.2008 15:21)