13: Sąrašai

Sąrašas - „list“ - leidžia saugoti reikšmių eilę. Vietoje to, kad rašytume programą su daug kintamųjų, galime turėti sąrašą x ir pasiekti jo elementus pagal numerius: x[0], x[1], x[2] ir t.t.  (Numeriai nurodomi laužtiniuose skliaustuose.) Numerį galima nurodyti, naudojant kintamąjį, pvz, x[i] ir x[i+1]. Tai leidžia, ciklų pagalba, tvarkyti didelius duomenų kiekius.

O kaip sukurti sąrašą?

myList = [101, 2014, 4.5]   # reikšmės išvardinamos tarp laužtinių skliaustų (atskirtos kableliais)
Tai sukuria sąrašą  myList. Sąraše yra 3 elementai/nariai. Kiekvienas sąrašo elementas turi savo numerį (indeksą): pirmojo elemento indeksas visada yra 0, antro elemento - 1, trečio - 2 ir t.t. Sąrašo elementai yra kaip kintamieji - jie pasiekiami:

«sarasoVardas»[«eilNr»]

Mūsų pavyzdyje, myList[0] yra kintamasis, kurio reikšmė yra 100, o print(myList[2]) atspausdintų 4.5.

Dažnai reikia sąrašą papildyti palaipsniui: tam naudojama sąrašo komanda (metodas) append( ), pavyzdžiui:

Pavyzdys: Sąrašo papildymas

Sąrašuose galima keisti bei pašalinti elementus (pagal numerį).

Pavyzdys: Elemento pakeitimas bei ištrynimas
Sąrašo elementų keitimas ir spausdinimas.

Kaip matote, numbers[0] reikšmė buvo pakeista (kaip ir bet kokio kintamojo).

Pabandykite nuspėti galutinę žemiau esančio pavyzdžio situaciją, o tada palyginkite savo spėjimą su rezultatu...

Pasirinkimo užduotis: Elementas kaip numeris
Ką atspausdina šis kodo fragmentas?

stuff = [2, 25, 80, 12]
stuff[stuff[0]] = stuff[3]
print(stuff)
Teisingai! Pažiūrėkite į antrą eilutę. Dešinėje esančio stuff[3] reikšmė yra 12. Kairiojoje pusėje esančio stuff[0] reikšmė yra 2, taigi, įstačius, stuff[stuff[0]] atitinka stuff[2]. Šio kintamojo reikšmė yra pakeičiama (iš 80) į 12.

Tai, ką Pitone vadiname list (sąrašu), kitose programavimo kalbose dažniausiai vadinama array (masyvu). Pitone taip pat yra  array  - naudojamas vienodo tipo reikšmėms saugoti (bet tik skaičiams arba simboliams). Tuo tarpu įprastame sąraše (list) vienu metu gali būti skaičiai, žodžiai ir bet kokios kitos reikšmės.

Dažniausiai pasitaikančios klaidos

Jei nurodysite per didelį elemento numerį, bus klaida:

Pavyzdys
Out-of-range error.

Aukščiau esančiame pavyzdyje myList turi 4 elementus. Pirmojo numeris yra 0, paskutiniojo - 3. Nurodę 4, 5 ar bet kurį didesnį skaičių, gausime klaidą.

Naudingos operacijos

Sąrašo ilgis: len(«list»).

Pavyzdyje len(«list») yra naudojamas kartu su range()  elementų numeriams išvardinti.

Pavyzdys
Kaip gauti sąrašo ilgį ir panaudoti jį sąrašo perrinkimui.

Prisiminkime, kad range(«pradžia», «pabaiga») generuoja seką nuo «pradžia» iki «pabaiga»-1 (t.y. pabaiga naudojama neimtinai).

Pabandykite naudoti len sąrašo viduriui rasti:

Programavimo pratimas: Aukso vidurys :)
Parašykite funkciją middle(L) kuri kaip argumentą gauna sąrašą L, ir grąžina viduryje esantį elementą. (Tarkime, kad bus paduodamas nelyginio ilgio sąrašas.) Pavyzdžiui, iškvietę middle([8, 0, 100, 12, 1]) turėtume gauti 100.
Žemiau įveskite testavimo veiksmus, pvz., print(myfunction("testiniai duomenys")).

Ar sąrašai yra panašūs į teksto eilutes (string)?

Tikrai taip! Tekstas yra tarsi simbolių sąrašas. Abiems naudojama len() funkcija bei elementų numeriai X[«nr»].   Abu jie yra numeruojamo tipo duomenys (angl. "sequence types"). BET, tekste simboliai negali būti keičiami pagal eil. nr.

Pavyzdys
Klaida, nes teksto elementui negalime priskirti reikšmės.

Dėl šios priežasties sąrašai yra vadinami "mutable" (kintančių elementų), o teksto eilutės - "immutable" (nekintančių elementų) tipo sekom. Daugiau apie tai --17-toje pamokoje..

Sąrašų sudėtis ir padauginimas

Iš  pamokos apie strint tipą, prisimename, kad yra įmanoma naudoti + ženklą dviejų tekstų sujungimui. Tą patį galima daryti ir su sąrašais.

Pavyzdys
Dviejų sąrašų sujungimas naudojant +.

Panašiai, galime naudoti daugybą*, kad padaugintume sąrašą (išvardintume jo elementus kelis kartus). Taip patogu sukurti norimo ilgio sąrašą.

Pavyzdys
Using *.

Norėdami išspręsti tolimesnį uždavinį, panaudokite vieną iš parodytų veiksmų ir for ciklą.

Programavimo pratimas: Numeriai sąraše
Parašykite funkciją naturalNumbers kuri gauna teigiamą sveiką skaičių n ir, sukūrusi, grąžina sąrašą iš numerių nuo 1 iki n (imtinai): [1, 2, ..., n].
Žemiau įveskite testavimo veiksmus, pvz., print(myfunction("testiniai duomenys")).

Eilutės pabaiga ir neigiami elementų numeriai (indeksai)

Norėdami gauti paskutinį sąrašo elementą, naudokite

«sarasas»[-1]

L[-k] grąžina k-tąjį lementą nuo sąrašo pabaigos. Pitonas šią išraišką paverčia į L[len(L)-k]. Šis trumpinys veikia ir su tekstu!

Programavimo pratimas: Palindromai
Palindromas tai žodis, kuris vienodai skaitomas pirmyn ir atgal. Pavyzdžiui žodis,

racecar

yra palindromas. Parašykite funkciją isPalindrome(S), kuri paimtų tekstą S ir grąžintų True jei tai palindromas, o False kitais atvejais.

Žemiau įveskite testavimo veiksmus, pvz., print(myfunction("testiniai duomenys")).

max irsum

Funkcija max, kaip matėme anksčiau, gražina didžiausią skaičių sąraše. Panašiai, funkcija sum(L) grąžina sąraše L esančių elementų sumą.

Pavyzdys

Programavimo pratimas: Sąrašo sandauga
Apibrėžkite funkciją prod(L), kuri grąžina sąrašo  L elementų sandaugą (angl. „product of list“).
Žemiau įveskite testavimo veiksmus, pvz., print(myfunction("testiniai duomenys")).

Sąrašo perrinkimas

„for“ ciklo  tikslesnė reikšmė angliškai būtų "for each" - jis iš eilės paima kiekvieną sąrašo reikšmę (prisiminkite 7c pamoką):

for x in Sar:
  «veiksmai, naudojantys x»
Pirmiausia x-ui yra priskiriama pirmoji Sar reikšmė ir atliekami veiksmai; tada x-ui yra priskiriama antroji Sar reikšmė ir atliekami veiksmai. Ir t.t. visiems elementams. Senesnės programavimo kalbos (C, Paskalis) šios savybės neturi, jose reikia naudoti indeksus.  Bet taip užrašyti patogiau - palyginkite, kaip atrodo su indeksais - papildomai „apkraunamas“ kodas:

for i in range(len(Sar)):   # range() duoda seką nuo 0 iki sąrašo paskutinio elemento
  x = Sar[i]
  «veiksmai, naudojantys x»
Indeksai reikalingi tik tada, jei reikia pakeisti sąrašo elementus, tačiau tai būna ne itin dažnai (bei patogumui dažnai naudojama "enumerate()" funkcija).

Štai vaizdingas sąrašo reikšmių perrinkimo ir atspausdinimo pavyzdys.

Programavimo pratimas: for «kintamasis» in «sąrašas»
Apibrėžkite funkciją prod(L) taip pat kaip ir anksčiau, bet šį kartą ji turėtų naudoti naujo tipo ciklą.
Žemiau įveskite testavimo veiksmus, pvz., print(myfunction("testiniai duomenys")).

"For each" ciklai yra tinkami ir tekstui: pabandykite for char in "hello".

Puiku! Galite keliauti į kitą pamoką, arba pabandyti papildomą užduotį.


Trumpo atsakymo užduotis: Paslaptis
Su kokia x reikšme mystery(x) patektų į nesibaigiantį ciklą?

def mystery(x):
  a = [0, 4, 0, 3, 2]
  while x > 0:
	x = a[x]
  return "Done"
Teisingai!

Sumaišytų eilučių užduotis: Moda
Moda yra dažniausiai sąraše pasitaikantis elementas. Pakeiskite programą taip, kad mode(L) teisingai rastų modą. Tarkime, kad L yra skaičių nuo 0 iki 9 sąrašas. (PS.:Tikrinimo duomenyse pasirūpinta, kad tik vienas skaičius būtų dažniausiai pasikartojantis.)
  • for i in L:
  • return i
  • for i in range(0, 10):
  • frequency = [0]*10
  • frequency[i] = frequency[i] + 1
  • if frequency[i]==max(frequency):
  • def mode(L):

Rikiavimas bei paieška sąraše

Tvarkant duomenis, rikiavimas ir paieška yra vieni svarbiausių/dažniausių veiksmų.

Paiešką galima atlikti, naudojant perrinkimą, pvz:

Pavyzdys: Paieškos algoritmas

Tačiau Python leidžia tai užrašyti trumpiau - kaip sąlygą  «ieskoma» in «Sar», kuri grąžins True/False:

Pavyzdys: Trumpas paieškos užrašas

Naudojant komandą index(), galima sužinoti, kurioje vietoje (kelintas) sąraše yra ieškomas elementas:

Pavyzdys: Ieškomo elemento numeris

Naudojant komandą  count( ), galima sužinoti, kiek kartų tam tikra reikšmė kartojasi sąraše.

Pavyzdys: Kiek kartų kartojasi?

Sąrašų rikiavimas yra plati programavimo tema (tam reikia naudoti ciklą cikle), bet Python turi paruoštus algoritmus, kurie iškviečiami viena eilute:

Pavyzdys: Sąrašo rikiavimas


Matricos - sąrašai iš sąrašų

Dažnai duomenų saugojimui ir analizei naudojamos matricos (lentelės). Tai yra tiesiog sąrašas iš sąrašų:

Pavyzdys: Matrica
Turime matricoje duomenis apie mokinių pažangumą. Kiekvienam suskaičuojame vidurkį ir nustatome ar jis pakankamai pažangus:

Kad geriau suprastumėte, išbandykite pavyzdį su "veiksmų sekimu" ;).

Kaip matome, matricą patogu nagrinėti eilutėmis. Bet kurią eilutę galima pasiekti pagal numerį: Pazymiai[0], Pazymiai[1] ir t.t. O eilutėje galima pasiekti bet kurį jos elementą, pvz., Pazymiai[2][0] yra reikšmė "Antanas".


Žodynai (dictionary)

Kita dažnai praverčianti duomenų struktūra yra žodynai ("dictionary") -- kitose kalbose vadinami atvaizdavimais ("map"). Juose reikšmės saugomos susietos poromis - pagal raktą (angl. "key") galima sužinoti jam priskirtą reikšmę (angl. "value") - kaip ir tikram žodyne. Programos kintamuosius Pythone irgi galima pasiekti kaip žodynus -- naudojant komandas locals() ir globals(). Žodyno poros išvardinamos tarp riestinių skliaustų { }, o pora susiejama dvitaškiu, pvz

asmens_info = {"vardas":"Petras",  "miestas":"NewYork", "amzius":21 }
Žodyne reikšmės saugomos ne iš eilės, o Python'ui patogia  tvarka - kad galėtų kuo greičiau rasti reikšmę pagal nurodytą raktą.  Žodyne naujo reikšmės (rakto) pridėjimas atrodo taip pat, kaip jau esančio pakeitimas, pvz:

asmens_info["turtas"] = 99000
asmens_info["miestas"] = "Kaunas"
Pavyzdys: Virtuali parduotuvė

Kad geriau suprastumėte, siūlome naudoti  "veiksmų sekimą".

Pavyzdys: alternatyvi žodyno sukūrimo sintaksė
Kartais žodyną patogiau sukurti taip (jei raktai yra paprasti žodžiai):

Sąrašas iš žodynų (panašiai, kaip matrica) gali būt naudojamas duomenų bazės informacijai saugoti/pateikti (raktus naudojant kaip stulpelių pavadinimus) - taip elgiasi NoSQL duombazės (kai nėra fiksuotos lentelių struktūros). O rimtiems duomenų tvarkymams dabar dažniausiai naudojamas Pandas paketas.

Interneto svetainėse siunčiami duomenys dažnai koduojami JSON formatu - jame naudojami sąrašai ir žodynai, kurie atrodo analogiškai kaip Python'e.

Aibės (set)

Aibės šiek tiek panašios į žodynus -- jose nesvarbi eilės tvarka ir kiekvienas elementas yra paminėtas tik vieną kartą. Su jom galima atlikti matematinius aibių sankirtos, sąjungos ir skirtumo veiksmus

A = set('abracadabra') # set(['a', 'r', 'b', 'c', 'd'])
B = set('alacazam') # set(['a', 'l', 'c', 'z', 'm'])
A & B # set(['a', 'c']) -- sankirta (elementai, kurie yra abiejose aibėse)
A - B # set(['r', 'd', 'b'])  -- skirtumas
A | B # set(['a', 'c', 'b', 'd', 'm', 'l', 'r', 'z'])  -- sąjunga (visi elementai iš abiejų aibių)


Patogios smulkmenos duomenų struktūroms

Įv. duomenų perrinkimas yra dažna užduotis, todėl Python'e yra pasistengta, kad tai būtų galima kuo trumpiau ir aiškiau užrašyti.

Pavyzdys: enumerate -- sąrašo elementai su numeriais

Pavyzdys: zip -- kelių sąrašų lygiagretus perrinkimas

Pavyzdys: zip -- 2 sąrašų supakavimas į žodyną

Pavyzdys: duomenų užklausos - list/dict comprehension

Pavyzdys: argumentų išpakavimas iš sąrašų/žodynų
Turint sąrašą, jo elementus galima pateikti funkcijai kaip argumentus. O žodyno poras galima paduoti kaip vardinius argumentus.