< eelmine | 10. nädala sisukord | järgmine > |
10.5 KORDAMINE
Töövoost, mida ikka kasutame
Vaatleme nüüd kordavalt töövoogu, mis mõningate variatsioonidega võib ette tulla paljude ülesannete puhul.
Olgu algandmed teatud kujul failis. Näiteks on vaadeldavate objektide kohta andmed ridade kaupa esitatud. Ridadel on eraldajateks tühikud või mingid muud sümbolid, näiteks semikoolonid. Selleks et üldse andmetega toimetada, peab programm need sisse lugema. Sisselugemisel võib juba midagi nende andmetega ette võtta, näiteks kuidagi teisendada või mõned andmed üldse välja jätta.
Sisselugemisel peaks andmed paigutama sobivasse andmestruktuuri näiteks kahemõõtmelisse järjendisse või sõnastikku.
Nüüd saab selle struktuuri abil juba andmeid analüüsida. Vajadusel saab näiteks nende andmete põhjal ka mingi teise andmestuktuuri tekitada. Ja siis ka juba tollega midagi teha.
Lõpuks saab tulemused ekraanile väljastada või hoopis mingitesse failidesse kirjutada.
Püüame nüüd näite varal kõik need etapid läbi teha.
Olgu andmed mingile üritusele, näiteks Tartusse laulupeole tulijate kohta. Olgu igal real kirjas maakond, selle keskuse kaugus Tartust, mitu meest on tulemas ja mitu naist.
Tartumaa : 0 : 302 : 400 Hiiumaa : 293 : 24 : 44 Harjumaa : 186 : 350 : 300 Ida-Virumaa : 131 : 280 : 270 Lääne-Virumaa : 123 : 200 : 160 Raplamaa : 149 : 56 : 46 Põlvamaa : 49 : 87 : 65 Viljandimaa : 78 : 170 : 170 Saaremaa : 322 : 154 : 128 Läänemaa : 238 : 105 : 102 Jõgevamaa : 53 : 79 : 82 Võrumaa : 70 : 75 : 89 Valgamaa : 90 : 65 : 76 Järvamaa : 103 : 124 : 120 Pärnumaa : 170 : 143 : 145
Küsime faili nime.
Failist sisselugemisel tahame andmed panna sõnastikku, kus võtmeks on maakonna nimi ja väärtuseks ennik, mis koosneb ülejäänud andmetest, mis maakonna kohta teada on. Seejuures paneme ennikusse kahekordse kauguse (Tartusse ja tagasi).
Teeme selleks funktsiooni, mis saab argumendiks failinime ja tagastab nõutud sõnastiku.
Arvutame, mitu kilomeetrit sõidavad kõik inimesed kokku.
Seejärel teeme selle sõnastiku põhjal kahemõõtmelise järjendi, mille ühes reas on meeste arvud ja teises reas naiste arvud. Selle järjendi põhjal arvutame, mitmes maakonnas on tulijate hulgas mehi rohkem, kui naisi.
Küsime faili nime, kuhu kirjutada.
Programm
def failist_sonastikku(failinimi): fail = open(failinimi) maakondade_sonastik = {} for rida in fail: #Teeme koolonite juurest katki jupid = rida.split(":") #Leiame väärtused järjendist maakond = jupid[0].strip() kaugus = int(jupid[1]) * 2 #edasi ja tagasi mehed = int(jupid[2]) naised = int(jupid[3]) #Moodustame sõnastiku ennik = (kaugus, mehed, naised) maakondade_sonastik[maakond] = ennik fail.close() return maakondade_sonastik def sonastikust_kauguste_summa(maakondade_sonastik): summa = 0 for maakond, vaartused in maakondade_sonastik.items(): kaugus = vaartused[0] mehi = vaartused[1] naisi = vaartused[2] summa += kaugus * mehi + kaugus * naisi return summa def sonastikust_tulijate_jarjend(maakondade_sonastik): mehed = [] naised = [] for maakond, vaartused in maakondade_sonastik.items(): mehed.append(vaartused[1]) naised.append(vaartused[2]) return [mehed, naised] def mehi_rohkem_kui_naisi(maakondade_sonastik): tulijad = sonastikust_tulijate_jarjend(maakondade_sonastik) maakondade_arv_kus_mehi_rohkem = 0 for i in range(len(tulijad[0])): #teame, et mõlemad järjendid on sama pikad mehi = tulijad[0][i] naisi = tulijad[1][i] if mehi > naisi: maakondade_arv_kus_mehi_rohkem += 1 return maakondade_arv_kus_mehi_rohkem maakondade_sonastik = failist_sonastikku("maakonnad.txt") kauguste_summa = sonastikust_kauguste_summa(maakondade_sonastik) print("Inimesed sõidavad kokku " + str(kauguste_summa) + " km.") print("Leidub", mehi_rohkem_kui_naisi(maakondade_sonastik), "maakonda, kus mehi tuleb laulupeole rohkem kui naisi.")
Sama programm hoopis funktsiooniga
Konkreetset probleemi saab lahendada mitmel erineval moel. Nüüd vaatlemegi sellist tüüpi ülesannet, kus on programm antud ja on ka öeldud, mida see programm teeb. Antud on ka teine programm, mis peaks tegema sama, aga kasutab seejuures ühte funktsiooni, millest on aga teada vaid nimi. Ülesandeks ongi nüüd koostada nõutud funktsioon, et kaks programmi võrdväärselt töötaksid.
Proovime siin ühte sellis ülesannet lahendada.
Järgnev programmilõik leiab kahemõõtmelise järjendi korral, kui paljudes ridades on positiivseid elemente.
positiivsega_ridu = 0 for i in range(len(a)): leidub_positiivne = False for j in range(len(a[i])): if a[i][j] > 0: leidub_positiivne = True break if leidub_positiivne: positiivsega_ridu += 1 print(positiivsega_ridu)
Koostada funktsioon on_positiivseid, mille puhul alltoodud programmilõik töötaks ülaltooduga võrdväärselt.
positiivsega_ridu = 0 for i in range(len(a)): if on_positiivseid(a[i]): positiivsega_ridu += 1 print(positiivsega_ridu)
On selge, et selleks, et esimene programm üldse töötaks peab enne antud lõiku olema defineeritud kahemõõtmeline arvude järjend a
.
Võiksime võtta testimiseks sellise järjendi, mille osades ridades on positiivseid elemente, aga osades mitte.
Ennekõike tuleb i
põhjalikult selgeks saada, mis toimub esimeses programmis, siis on lootust teine programm samamoodi tööle saada. Paneme ka tähele, et mõlema programmi algus ja lõpp on täiesti samad.
Kui ridarealt läbi analüüsida, saame järgmised ideed.
positiivsega_ridu = 0 # Paneme tähele, et see suurus lõpuks väljastatakse for i in range(len(a)): # len(a) on 2d järjendi pikkus ehk ridade arv # Seega välimine tsükkel võtab igal sammul uue reaindeksi leidub_positiivne = False # Igal välimise tsükli sammul saab leidub_positiivne väärtuseks False for j in range(len(a[i])): # len(a[i]) on konkreetse rea elementide arv # Sisemine tsükkel vaatab konkreetse rea elemente järjest if a[i][j] > 0: leidub_positiivne = True break # Kui vaadeldav element on positiivne, siis saab leidub_positiivne # väärtuseks True ja sisemisest tsüklist tullakse välja, sest ongi # positiivne leitud ja edasi pole vaja otsida if leidub_positiivne: positiivsega_ridu += 1 # Kui konkreetse reaga on klaar, siis otsustatakse, kas tuleb # suurendada loendajat print(positiivsega_ridu) # Lõpuks loendaja väärtus väljastatakse.
Kui vaatame nüüd teist programmi, siis näeme, et selle kontroll, kas konkreetses reas on positiivseid elemente, on usaldatud funktsioonile on_positiivseid
.
positiivsega_ridu = 0 for i in range(len(a)): if on_positiivseid(a[i]): positiivsega_ridu += 1 print(positiivsega_ridu)
Mõtleme läbi, mis tüüpi on funktsiooni on_positiivseid
argument ja mis tüüpi väärtus tuleb tagastada. Näeme, et funktsioonile antakse ette a[i]
, mis antud kontekstis on kahemõõtmelise järjendi rida ehk siis arvude järjend. Paneme tähele, et seda funktsiooni kasutatakse if-lause tingimusena. Seega peab tagastatav väärtus olema tõeväärtustüüpi - True
või False
.
True
peaks tagastatama, kui selles reas on vähemalt üks positiivne element ja False
vastasel juhul. Lahenduseks sobib näites selline variant.
def on_positiivseid(rida): for i in range(len(rida)): if rida[i] > 0: return True return False
Palun katsetage ja veenduge selles ise.
< eelmine | 10. nädala sisukord | järgmine > |