Kahemõõtmeline järjend. Failist lugemine kahemõõtmelisse järjendisse
Kahemõõtmeline järjend
Järjend on Pythoni andmestruktuur, mille abil saab ühes muutujas hoida mitut väärtust. Näiteks muutujale kursus omistatakse järjend, mis koosneb kahest sõnest:
kursus = ['Programmeerimine', '2024']
Varem oleme kasutanud peamiselt järjendeid, mille elemendid on arvud või sõned. Tegelikult võime järjendis hoida igasugust tüüpi väärtuseid, kusjuures järjendi elemendid võivad Pythonis isegi eri tüüpi olla:
huvitav_jarjend = ['Taisi Telk', 29, True]
Muuhulgas võivad järjendi elementideks olla ka teised järjendid:
kahemootmeline_jarjend = [[30, 2], [42]]
Siin on tegemist järjendiga, millel on kaks elementi. Esimene element on järjend, mille elementideks on arvud 30 ja 2, ning teine on järjend, mille ainsaks elemendiks on 42. Kasutame värve, et rõhutada järjendi mitmetasemelist ülesehitust.
järjend = [[30, 2], [42]]
Punane tähistab välimist järjendit ja sinine tema elementjärjendeid. Nende sisemiste järjendite elemendid on hallid.
See on meie esimene kahemõõtmeline andmestruktuur. Kahemõõtmeliseks nimetatakse seda sellepärast, et kõige sisemiste elementide (eelmises näites 30, 2, 42) asukoht määratakse kahe mõõtme abil. Esiteks tuleb määrata, mitmendas sisemises järjendis element asub ja teiseks, mitmes element ta on selle väljavalitud sisemise järjendi elementide hulgas. Seejuures peame meeles, et järjendi elemente nummerdatakse indeksite abil ja indeksid algavad alati nullist.
Näiteks kui tahame eelmises näites järjend = [[30, 2], [42]] tekitatud järjendist saada kätte väärtust 2, siis leiame, et ta asub välimises järjendis indeksiga 0 (esimene element) ja selle sees olevas sisemises järjendis on ta element indeksiga 1 (teine element). Koodis pannakse see kirja niimoodi:
kahemootmeline_jarjend = [[30, 2], [42]] print(kahemootmeline_jarjend[0][1]) # Väljastab 2
Kahemõõtmelise järjendi sisemiste elementide poole pöördumiseks paigutatakse pärast muutuja nime kaks paari nurksulge. Esimesed nurksulud sisaldavad indeksit, mis määrab vaadeldava sisemise järjendi. Teiste nurksulgude sisse kirjutatakse indeks, mis määrab elemendi asukoha saadud sisemises järjendis.
Tähele tuleb panna, et tavaline “inimlik” ja programmeerimise kõnepruuk erinevad. Rääkides järjendi a esimese elemendi teisest elemendist peetakse silmas ilmselt elementi a[0][1]
.
Kahemõõtmelist järjendit võime visualiseerida ka kahe ruumimõõtme abil. Sel juhul võiks esimesest indeksist mõelda kui rea indeksist ja teisest kui veeru indeksist. Siis näeb meie näitejärjend välja selline:
30 2 42
Elemendi väärtusega 2 leiab tõesti sellest tabelist reast indeksiga 0 ja veerust indeksiga 1.
Rohkemate mõõtmetega järjendid
Kui järjendite sees saab hoida järjendeid, siis kas nende sees saab hoida omakorda veel järjendeid? Jah, tehniliselt ei piira meid miski tekitamast ükskõik kui sügavaid struktuure. Võime isegi mõelda järjendite peale, kus igal sügavusastmel võib olla kas n-ö lõppelemente või veel järjendeid. Sellist andmestruktuuri võib nimetada n-mõõtmeliseks järjendiks. Kuidas tegutseda andmestruktuuriga, mille sügavust me ei tea? Sellest räägime selle kursuse viimastel nädalatel rekursiivsete andmestruktuuride juures.
Järjendite järjend
Eelmises osas sai räägitud, et kahemõõtmelisest järjendist saab elementidele ligi, kasutades kahte järjestikust nurksulgudesse paigutatud indeksit:
jarjendite_jarjend = [[1, 2, 4], [-1, 5, 0], [], ['sõne']] print(jarjendite_jarjend[0][2]) # Väljastab 4
Samuti võime kahemõõtmelist järjendit vaadelda tavalise ühemõõtmelise järjendina, mille elemendid on lihtsalt mingid järjendid, mille sisu meid ei huvitagi. Näiteks võib meid huvitada ainult selle välimise järjendi elementide arv:
jarjendite_jarjend = [[1, 2, 4], [-1, 5, 0], [], ['sõne']] print(len(jarjendite_jarjend)) # Väljastab 4
Või äkki hoopis tahame teha midagi tema viimase elemendiga (järjendiga), hoolimata otseselt sellest, mis elemendid selle sees on:
jarjendite_jarjend = [[1, 2, 4], [-1, 5, 0], [], ['sõne']] viimane = jarjendite_jarjend[-1] print(len(viimane)) # Väljastab 1 print(viimane.count(5)) # Väljastab 0 print(viimane.count('sõne')) # Väljastab 1 print(viimane) # Väljastab ['sõne']
Kahemõõtmelist järjendit võime vastavalt vajadusele käsitleda kas
- teatud tüüpi tabelina, kus iga elemendi asukoht on määratud kahe indeksiga või
- tavalise ühemõõtmelise järjendina, mille elemendid on järjendi tüüpi väärtused.
Näiteks järjendi
inimesed = [['Kersti', 49, False], ['Jüri', 40, True], ['Eiki', 65, True]]
puhul on esimene käsitlus sobiv, kui peame näiteks leidma, kui vana on järjendi kolmas inimene. Teine käsitlus on hea, kui peame lihtsalt kokku lugema, mitme inimese andmed järjendis on.
Nii saame leida veel näiteks iga sisemise järjendi (rea) maksimaalse elemendi:
lst = [[1, 3, 2], [4, 5, 6], [7, 8, 9]] for rida in lst: print(max(rida))
Sammhaaval järjendisse laskumine
Tegelikult võime kahemõõtmelise järjendi teise taseme (sügavatele) elementidele ligi pääseda ka kahe sammuga: esmalt eraldame meid huvitava sisemise järjendi ning siis valime sellest omakorda sobiva elemendi.
jarjendite_jarjend = [[1, 2, 4], [-1, 5, 0], [], ['sõne']] sisemine = jarjendite_jarjend[1] print(sisemine[0]) # Väljastab -1
Pythoni sisemuses toimub protsess samamoodi, olenemata sellest, kas valime esmalt välja rea ning sellest elemendi või kasutame korraga kahte indeksit.
Kahemõõtmelised järjendid polegi tegelikult Pythoni jaoks midagi oluliselt erinevat ühemõõtmelisest järjendist. Seega saame ka kahemõõtmelisi järjendeid tekitada juba tuttavatel viisidel:
jarjendite_jarjend = [] # Praegu on see ühemõõtmeline järjend jarjendite_jarjend.append([1, 2, 4]) # Lisame sisemise järjendi - nüüd on kahemõõtmeline jarjendite_jarjend += [[-1, 5, 0]] # Pane tähele! Kahekordsed nurksulud! tyhi = [] jarjendite_jarjend.append(tyhi) viimane = [] viimane.append('sõne') jarjendite_jarjend.append(viimane) print(jarjendite_jarjend) # Väljastab [[1, 2, 4], [-1, 5, 0], [], ['sõne']]
Selgitame natuke põhjalikumalt, miks on jarjendite_jarjend += -1, 5, 0?
puhul just kahekordsed nurksulud. Nii lisatakse uueks elemendiks kogu järjend [-1, 5, 0]
. jarjendite_jarjend += [-1, 5, 0]
puhul lisataks iga arv eraldi elemendina.
Eritüübiliste elementidega järjendid
Kuigi Python lubab hoida ühes järjendis mitut eri tüüpi väärtust, on see üpris veaohtlik, sest programmeerija peab siis meeles pidama, mis tüüpi väärtused kuskil asuvad. Kui võimalik, siis on mõistlik püüda hoida eri tüüpi väärtuseid erinevates järjendites.
Maatriks
Kui järjendis (või muus tabelis) on igas elemendis sama arv alamelemente (ehk tabeli igal real on sama arv väärtusi), nimetatakse seda struktuuri maatriksiks. Seda matemaatikast pärinevat terminit kasutame ka edaspidi.
Failist lugemine kahemõõtmelisse järjendisse
Järjendi peatükis tõime näite failist, kus oli ühel real tühikuga eraldatult päeva miinimum- ja maksimumtemperatuurid:
Näiteks, kui meil on failis arvud.txt ühel real päeva miinimum- ja maksimumtemperatuurid:
5.0 15.2 6.2 12.4 7.2 12.3 5.1 10.5 4.8 9.5 4.5 10.8 6.2 12.5
Siis saame väljastada ekraanile ühe rea elemendid:
fail = open("arvud.txt") for rida in fail: osad = rida.split() print(float(osad[1]), float(osad[0])) fail.close()
Seda programmi tahaks nüüd täiendada selliselt, et temperatuurid loetakse failist järjendisse, kus iga element on omakorda järjend vastava päeva miinimum- ja maksimumtemperatuuriga. Selleks loome tühja järjendi temperatuurid
ja tsüklis omakorda ajutise järjendi ühe_päeva_temperatuurid
, kuhu saame vastava päeva miinimum- ja maksimumtemperatuurid lisada:
temperatuurid = [] fail = open("arvud.txt") for rida in fail: ühe_päeva_temperatuurid = [] osad = rida.split() ühe_päeva_temperatuurid.append(float(osad[1])) ühe_päeva_temperatuurid.append(float(osad[0])) temperatuurid.append(ühe_päeva_temperatuurid) fail.close() print(temperatuurid)
Katseta, mis selle programmiga ekraanile väljastatakse.