8. Zoznamy¶
Už poznáme tieto typy údajov:
jednoduché:
číselné
int
afloat
logické
bool
postupnosti:
postupnosti znakov
str
postupnosti riadkov - otvorený textový súbor
postupnosti čísel - pomocou
range()
Dátová štruktúra zoznam¶
v Pythone sa tento typ volá list
je to vlastne postupnosť hodnôt ľubovoľných typov (zvykne sa používať aj pojem kolekcia, po anglicky collection)
hovoríme, že typ zoznam sa skladá z prvkov
okrem názvu zoznam, môžeme používať aj názov tabuľka alebo pole (pole väčšinou pre zoznamy hodnôt rovnakého typu)
tento typ sa podobá na pole v iných jazykoch (napríklad v Pascale je to dynamické pole, ktorého ale hodnoty musia byť rovnakého typu) - často im tak budeme hovoriť aj v Pythone
Zoznamy vytvárame vymenovaním prvkov v hranatých zátvorkách, v príklade ich hneď aj priradíme do rôznych premenných:
>>> teploty = [10, 13, 15, 18, 17, 12, 12]
>>> nakup = ['chlieb', 'mlieko', 'rozky', 'jablka']
>>> studenti = ['Juraj Janosik', 'Emma Drobna', 'Ludovit Stur', 'Pavol Habera', 'Margita Figuli']
>>> zviera = ['pes', 'Dunco', 2011, 35.7, 'hneda']
>>> prazdny = [] # prázdny zoznam
>>> print(teploty)
[10, 13, 15, 18, 17, 12, 12]
>>> type(zviera)
<class 'list'>
Všimnite si, že niektoré z týchto zoznamov majú všetky prvky rovnakého typu (napríklad, všetky prvky sú celé čísla alebo všetky sú reťazce).
Operácie so zoznamami¶
Základné operácie so zoznamami fungujú skoro presne rovnako, ako ich vieme používať so znakovými reťazcami:
indexovanie pomocou hranatých zátvoriek
[ ]
- je úplne rovnaké ako pri reťazcoch: indexom je celé číslo od 0 do počet prvkov zoznamu - 1, alebo je to záporné číslo, napríklad:>>> zviera[0] 'pes' >>> nakup[1] 'mlieko' >>> studenti[-1] 'Margita Figuli' >>> ['red', 'blue', 'yellow', 'green'][1] 'blue' >>> ['red', 'blue', 'yellow'][2][4] 'o'
zreťazenie pomocou operácie
+
označuje, že vytvoríme nový väčší zoznam, ktorý bude obsahovať najprv prvky prvého zoznamu a za tým všetky prvky druhého zoznamu, napríklad:>>> nakup2 = ['zosity', 'pero', 'vreckovky'] >>> nakup + nakup2 ['chlieb', 'mlieko', 'rozky', 'jablka', 'zosity', 'pero', 'vreckovky'] >>> studenti = studenti + ['Karel Capek'] >>> studenti ['Juraj Janosik', 'Emma Drobna', 'Ludovit Stur', 'Pavol Habera', 'Margita Figuli', 'Karel Capek'] >>> prazdny + prazdny [] >>> [1] + [2] + [3, 4] + [] + [5] [1, 2, 3, 4, 5]
viacnásobné zreťazenie pomocou operácie
*
označuje, že daný zoznam sa navzájom zreťazí určený počet krát, napríklad:>>> jazyky = ['Python', 'Pascal', 'C++', 'Java', 'C#'] >>> vela = 3 * jazyky >>> vela ['Python', 'Pascal', 'C++', 'Java', 'C#', 'Python', 'Pascal', 'C++', 'Java', 'C#', 'Python', 'Pascal', 'C++', 'Java', 'C#'] >>> sto_krat_nic = 100 * [None] >>> sto_krat_nic [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None] >>> prazdny * 1000 []
zisťovanie prvku pomocou
in
označuje, či sa nejaká hodnota nachádza v danom zozname, napríklad:>>> 'Pavol Habera' in studenti True >>> 'pero' in nakup False >>> 'pascal' in jazyky False >>> prazdny in sto_krat_nic False >>> teploty = [10, 13, 15, 18, 17, 12, 12] >>> 18 in teploty True >>> [18, 17] in teploty False
V poslednom príklade testujeme, či sa dvojprvkový zoznam
[18, 17]
nachádza niekde v zoznameteploty
. Lenže tento zoznam obsahuje len celé čísla a žiaden prvok nie je typu zoznam. Hoci pre znakové reťazce fungovalo hľadanie podreťazca, napríklad:>>> 'th' in 'Python' True
pre zoznamy táto analógia nefunguje.
Ešte si pripomeňte zápis negácie takéhoto testu, ktorý analogicky funguje pre reťazce aj zoznamy:
>>> not 'Y' in 'Python' True >>> 'Y' not in 'Python' True >>> 'str' not in ['pon', 'uto', 'str', 'stv', 'pia', 'sob', 'ned'] False >>> 'štv' not in ['pon', 'uto', 'str', 'stv', 'pia', 'sob', 'ned'] True
Pripomeňme si, ako vyzerajú premenné a ich hodnoty v pamäti Pythonu. Urobme toto priradenie:
ab = [2, 3, 5, 7, 11]
Do pamäti mien (globálny menný priestor) pribudne jeden identifikátor premennej ab
a tiež referencia na päťprvkový zoznam [2, 3, 5, 7, 11]
. Tento zoznam môžeme v pamäti hodnôt vizualizovať ako päť vedľa seba položených škatuliek, pričom v každej je referencia na príslušnú hodnotu:

Je dobre si uvedomiť, že momentálne máme v pamäti 6 premenných, jedna z nich je ab
(je typu list
) a zvyšných päť je ab[0]
, ab[1]
, ab[2]
, ab[3]
a ab[4]
(všetky sú typu int
).
Prechádzanie prvkov zoznamu¶
Tzv. iterovanie najčastejšie pomocou for-cyklu. Napríklad:
>>> teploty
[10, 13, 15, 18, 17, 12, 12]
>>> for i in range(7):
print(f'{i}. deň', teploty[i])
0. deň 10
1. deň 13
2. deň 15
3. deň 18
4. deň 17
5. deň 12
6. deň 12
Využili sme indexovanie prvkov zoznamu indexmi od 0 do 6. Ak nepotrebujeme pracovať s indexmi, ale stačia nám samotné hodnoty, zapíšeme:
>>> for prvok in teploty:
print(prvok, end=', ')
10, 13, 15, 18, 17, 12, 12,
Prípadne, vieme využiť enumerate
:
>>> for i, prvok in enumerate(teploty):
print(f'{i+1}. deň', prvok)
1. deň 10
2. deň 13
3. deň 15
4. deň 18
5. deň 17
6. deň 12
7. deň 12
Môžeme zapísať aj výpočet priemernej teploty:
teploty = [10, 13, 15, 18, 17, 12, 12]
sucet = 0
for prvok in teploty:
sucet += prvok
priemer = sucet / 7
print(f'priemerná teplota je {priemer:.1f}') # formátovanie desatinného čísla na jedno miesto
priemerná teplota je 13.9
Podobne vieme zistiť, napríklad maximálnu hodnotu v zozname:
mx = teploty[0]
for prvok in teploty:
if mx < prvok:
mx = prvok
print('najteplejšie bolo', mx, 'stupňov')
najteplejšie bolo 18 stupňov
Alebo zistenie počtu nadpriemerne teplých dní:
teploty = [10, 13, 15, 18, 17, 12, 12]
sucet = 0
for prvok in teploty:
sucet += prvok
priemer = sucet / 7
pocet = 0
for prvok in teploty:
if prvok > priemer:
pocet += 1
print('počet nadpriemerne teplých dní', pocet)
počet nadpriemerne teplých dní 3
Z týchto jednoduchých príkladov môžeme zapísať šablóny, ktoré niečo zisťujú o prvkoch zoznamu.
Napríklad, nasledovný program vypíše prvky zoznamu do jedného riadku:
zoznam = [47, 'ab', -13, 22, 9, 25]
print('prvky zoznamu:', end=' ')
for prvok in zoznam:
print(prvok, end=' ')
print()
dostaneme výpis:
prvky zoznamu: 47 ab -13 22 9 25
Ale tento program:
for i in range(10):
index = i % 4
farba = ['red', 'blue', 'yellow', 'green'][index]
print(farba)
pristupuje k niektorým prvkom aj viackrát a vypíše:
red
blue
yellow
green
red
blue
yellow
green
red
blue
Tento for-cyklus by sme mohli zapísať aj takto:
for i in range(10):
print(['red', 'blue', 'yellow', 'green'][i%4])
Zmena hodnoty prvku zoznamu¶
Dátová štruktúra zoznam je meniteľný typ (tzv. mutable) - môžeme meniť hodnoty prvkov zoznamu, napríklad takto:
>>> studenti[3]
'Pavol Habera'
>>> studenti[3] = 'Janko Hrasko'
>>> studenti[2] = 'Guido van Rossum'
>>> studenti
['Juraj Janosik', 'Emma Drobna', 'Guido van Rossum', 'Janko Hrasko', 'Margita Figuli', 'Karel Capek']
Môžeme zmeniť hodnoty prvkov zoznamu aj v cykle, ale k prvkom musíme pristupovať pomocou indexov, napríklad sme zistili, že náš teplomer ukazuje o 2 stupne menej ako je reálna teplota, preto opravíme všetky prvky zoznamu:
teploty = [10, 13, 15, 18, 17, 12, 12]
for i in range(7):
teploty[i] = teploty[i] + 2
print(teploty)
[12, 15, 17, 20, 19, 14, 14]
Krajšie by sme to zapísali s využitím štandardnej funkcie len()
, ktorá vráti počet prvkov zoznamu:
teploty = [10, 13, 15, 18, 17, 12, 12]
for i in range(len(teploty)):
teploty[i] += 2
print(teploty)
[12, 15, 17, 20, 19, 14, 14]
Uvedomte si, že ak by sme prvky zoznamu neindexovali, ale prechádzali by sme ich priamo cez premennú cyklu prvok
:
teploty = [10, 13, 15, 18, 17, 12, 12]
for prvok in teploty:
prvok += 2
print(teploty)
nebude to fungovať:
[10, 13, 15, 18, 17, 12, 12]
Samotný zoznam sa tým nezmení: menili sme len obsah premennej cyklu prvok
, ale tým sa nezmení obsah zoznamu.
Je dobré si predstaviť, čo sa deje v pamäti pri zmene hodnoty prvku zoznamu. Zoberme si pôvodný päť prvkový zoznam prvočísel:
ab = [2, 3, 5, 7, 11]
Zmenou obsahu jedného prvku zoznamu sa zmení jediná referencia, všetko ostatné zostáva bez zmeny:
ab[2] = 55
dostávame:

Priraďovaním do jedného prvku zoznamu sa tento zoznam modifikuje, hovoríme, že priradenie do prvku je mutable operácia. Ukážme šablónu, pomocou ktorej vieme v cykle priradiť do rôznych prvkov rôzne hodnoty.
Napríklad pre vytvorenie zoznamu prvých n
druhých mocnín čísel od 0
do n-1
:
n = int(input('zadaj n: '))
mocniny = [None] * n
for i in range(n):
mocniny[i] = i * i
print(mocniny)
zadaj n: 14
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169]
Štandardné funkcie so zoznamami¶
Nasledovné funkcie fungujú nielen so zoznamami, ale s ľubovoľnou postupnosťou hodnôt. V niektorých prípadoch však nemajú zmysel a vyhlásia chybu (napríklad číselný súčet prvkov znakového reťazca).
funkcia
len(postupnosť)
-> vráti počet prvkov postupnostifunkcia
sum(postupnosť)
-> vypočíta číselný súčet prvkov postupnostifunkcia
max(postupnosť)
-> vráti maximálny prvok postupnosti (t.j. jeho hodnotu)funkcia
min(postupnosť)
-> vráti minimálny prvok postupnosti
Predchádzajúci príklad, v ktorom sme počítali priemernú, minimálnu aj maximálnu teplotu, prepíšeme:
teploty = [10, 13, 15, 18, 17, 12, 12]
sucet = sum(teploty)
maximum = max(teploty)
minimum = min(teploty)
priemer = sucet / len(teploty)
print('priemerná teplota je', f'{priemer:.1f}')
print('minimálna teplota je', minimum)
print('maximálna teplota je', maximum)
priemerná teplota je 13.9
minimálna teplota je 10
maximálna teplota je 18
Čo sa dá zapísať úspornejšie, ale menej čitateľne aj takto:
teploty = [10, 13, 15, 18, 17, 12, 12]
print('priemerná teplota je', f'{sum(teploty)/len(teploty):.1f}')
print('minimálna teplota je', min(teploty))
print('maximálna teplota je', max(teploty))
Funkcia list()¶
Už máme nejaké skúsenosti s tým, že v Pythone každý základný typ má definovanú svoju konverznú funkciu, pomocou ktorej sa dajú niektoré hodnoty rôznych typov prekonvertovať na daný typ. Napríklad
int(3.14)
-> vráti celé číslo3
int('37')
-> vráti celé číslo37
str(22 / 7)
-> vráti reťazec'3.142857142857143'
str(2 < 3)
-> vráti reťazec'True'
Podobne funguje aj funkcia list(hodnota)
:
parametrom musí byť iterovateľná hodnota, t.j. nejaká postupnosť, ktorá sa dá prechádzať (iterovať), napríklad for-cyklom
funkcia
list()
túto postupnosť rozoberie na prvky a z týchto prvkov poskladá nový zoznamparameter môže chýbať, vtedy vygeneruje prázdny zoznam
Napríklad:
>>> list(zviera) # kópia existujúceho zoznamu
['pes', 'Dunco', 8, 35.7, 'hneda']
>>> list(range(5, 16))
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
>>> list('Python')
['P', 'y', 't', 'h', 'o', 'n']
>>> list() # prázdny zoznam
[]
>>> list(3.14)
...
TypeError: 'float' object is not iterable
Ak nejaký súbor obsahuje tieto riadky:
Aká
práca,
taká
pláca.
aj toto Python vidí ako postupnosť (otvorený súbor sa dá prechádzať for-cyklom ako postupnosť riadkov) a preto:
>>> list(open('subor.txt', encoding='utf-8'))
['Aká\n', 'práca,\n', '\n', 'taká\n', 'pláca.\n']
Rezy¶
Keď sme v znakovom reťazci potrebovali zmeniť nejaký znak, zakaždým sme museli vyrobiť kópiu reťazca, napríklad:
>>> retazec = 'Monty Python'
>>> retazec[4] = 'X' # takto sa to nedá
...
TypeError: 'str' object does not support item assignment
>>> retazec = retazec[:4] + 'X' + retazec[5:]
>>> retazec
'MontX Python'
Využili sme tu rezy (slice), t.j. získavanie podreťazcov. To isté sa dá použiť aj pri práci so zoznamami, lebo aj s nimi fungujú rezy, napríklad:
>>> jazyky
['Python', 'Pascal', 'C++', 'Java', 'C#']
>>> jazyky[1:3]
['Pascal', 'C++']
>>> jazyky[-3:]
['C++', 'Java', 'C#']
>>> jazyky[:-1]
['Python', 'Pascal', 'C++', 'Java']
Samozrejme, že pritom funguje aj určovanie kroku, napríklad:
>>> jazyky[1::2]
['Pascal', 'Java']
>>> jazyky[::-1]
['C#', 'Java', 'C++', 'Pascal', 'Python']
Uvedomte si, že takéto rezy nemenia obsah samotného zoznamu a preto hovoríme, že sú immutable.
Priraďovanie do rezu¶
Keď iba vyberáme nejaký podzoznam pomocou rezu, napríklad zoznam[od:do:krok]
, takáto operácia s pôvodným zoznamom nič nerobí (len vyrobí úplne nový zoznam). Lenže my môžeme obsah zoznamu meniť aj takým spôsobom, že zmeníme len jeho nejakú časť. Takže rez zoznamu môže byť na ľavej strane priraďovacieho príkazu a potom na pravej strane priraďovacieho príkazu musí byť nejaká postupnosť (nemusí to byť zoznam). Priraďovací príkaz teraz túto postupnosť prejde, zostrojí z nej zoznam a ten vloží namiesto udaného rezu.
Preštudujte nasledovné príklady:
>>> zoz = list(range(0, 110, 10))
>>> zoz
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
>>> zoz[3:6] = ['begin', 'end'] # tri prvky sa nahradili dvomi
>>> zoz
[0, 10, 20, 'begin', 'end', 60, 70, 80, 90, 100]
>>> zoz[6:7] = [111, 222, 333] # jeden prvok sa nahradil tromi
>>> zoz
[0, 10, 20, 'begin', 'end', 60, 111, 222, 333, 80, 90, 100]
>>> abc = list('Python')
>>> abc
['P', 'y', 't', 'h', 'o', 'n']
>>> abc[2:2] # rez dĺžky 0
[]
>>> abc[2:2] = ['dve', 'slova'] # rez dĺžky 0 sa nahradí dvomi prvkami
>>> abc
['P', 'y', 'dve', 'slova', 't', 'h', 'o', 'n']
>>> prvo = [2, 3, 5, 7, 11]
>>> prvo[1:-1]
[3, 5, 7]
>>> prvo[1:-1] = [] # rez dĺžky 3 sa nahradí žiadnymi prvkami
>>> prvo # prvky sa takto vyhodili
[2, 11]
Pozor! Všetky tieto príklady modifikujú pôvodný zoznam, teda priraďovanie do rezu je mutable operácia.
Zoznam ako parameter funkcie¶
Už predtým sme zisťovali priemernú teplotu zo zoznamu nameraných hodnôt. Teraz z toho vieme urobiť funkciu, napríklad:
def priemer(zoznam):
sucet = 0
pocet = 1
for prvok in zoznam:
sucet += prvok
pocet += 1
return sucet / pocet
Keďže pomocou štandardných funkcií sum()
a len()
vieme veľmi rýchlo zistiť súčet aj počet prvkov zoznamu, môžeme to zapísať elegantnejšie:
def priemer(zoznam):
return sum(zoznam) / len(zoznam)
Ďalšia funkcia zisťuje počet výskytov nejakej konkrétnej hodnoty v zozname:
def pocet(zoznam, hodnota):
vysl = 0
for prvok in zoznam:
if prvok == hodnota:
vysl += 1
return vysl
a naozaj funguje:
>>> pocet([1, 2, 3, 2, 1, 2], 4)
0
>>> pocet([1, 2, 3, 2, 1, 2], 2)
3
Zaujímavé je aj to, že funkcia funguje nielen pre zoznamy, ale pre ľubovoľnú postupnosť (iterovateľnú štruktúru), napríklad:
>>> pocet('bla-bla-bla', 'l')
3
>>> pocet('bla-bla-bla', 'la') # v postupnosti znakov sa 'la' nenachádza
0
Pre znaky táto funkcia robí skoro to isté ako metóda count()
, teda zápis:
>>> 'bla-bla-bla'.count('l')
3
naša funguje úplne rovnako ako funkcia pocet()
. Aj pre zoznamy existuje metóda count
, ktorá robí presne to isté ako naša funkcia pocet()
.
Metódy¶
Už vieme, že metódami voláme také funkcie, ktoré fungujú s nejakou hodnotou: za túto hodnotu dávame bodku (preto tzv. bodková notácia) a samotné meno funkcie s prípadnými parametrami. V prípade zoznamov to vyzerá takto:
zoznam.funkcia(parametre)
Pre zoznamy existujú tieto dve metódy, ktoré nemodifikujú ich obsah a preto vieme, že sú immutable.
Metódu môžeme použiť nielen s premennou typu zoznam, napríklad:
>>> zoz = [1, 2, 3, 2, 1, 2]
>>> zoz.count(2)
3
>>> zoz.count(4)
0
Ale aj priamo s hodnotou zoznam, napríklad:
>>> [0, 1, 0, 0, 1, 0, 1, 0, 0].count(1)
3
Alebo s výrazom, ktorý je typu zoznam:
>>> ([3, 7] * 100 + [7, 8] * 50).count(7)
150
Aj túto metódu môžeme použiť rôznym spôsobom, napríklad s premennou typu zoznam:
>>> farby = ['red', 'blue', 'red', 'blue', 'yellow']
>>> farby.index('blue')
1
>>> farby.index('green')
...
ValueError: 'green' is not in list
Pri používaní tejto metódy musíme dávať pozor, aby nám program nepadal, keď sa daná hodnota v zozname nenachádza. Napríklad takto:
farby = ['red', 'blue', 'red', 'blue', 'yellow']
if 'green' in farby:
index = farby.index('green')
else:
print('"green" sa v zozname nenachádza')
'green' sa v zozname nenachádza
Všetky ďalšie metódy, ktoré tu uvedieme, sú mutable, teda budú modifikovať samotný zoznam.
Napríklad volanie:
>>> ab = [2, 3, 5, 7, 11]
>>> ab.append(13)
>>> ab
[2, 3, 5, 7, 11, 13]
takto sa zmení vizualizácia pamäte pre premennú ab
:

Zrejme nemá zmysel volať túto metódu s hodnotou typu zoznam namiesto premennej. Hoci to funguje dobre, nemáme šancu zistiť, ako vyzerá daný zoznam s pridaným prvkom:
>>> [1, 2, 3].append(4)
Niekde v pamäti hodnôt sa vyrobil zoznam [1, 2, 3, 4]
, na ktorý ale nemáme žiadnu referenciu.
Vďaka tejto metóde sa oplatí naučiť aj druhý spôsob vytvárania zoznamu.
Príklady:
zoznam hodnôt postupnosti čísel
range(2, 100, 13)
:zoznam = [] for i in range(2, 100, 13): zoznam.append(i) print(zoznam)
[2, 15, 28, 41, 54, 67, 80, 93]
v tomto konkrétnom prípade sa to dalo zapísať aj takto výrazne jednoduchšie:
zoznam = list(range(2, 100, 13)) print(zoznam)
zoznam reťazcov, ktoré sú vytvorené z mocnín
2
a obsahujú cifru7
:zoznam = [] for i in range(30): hodnota = str(2 ** i) if '7' in hodnota: zoznam.append(hodnota) print(zoznam)
['32768', '131072', '1048576', '2097152', '16777216', '67108864', '134217728', '536870912']
Napríklad:
>>> abc = ['raz', 'dva', 'tri']
>>> for i in range(4):
abc.pop()
'tri'
'dva'
'raz'
...
IndexError: pop from empty list
Napríklad:
>>> abc = ['raz', 'dva', 'tri']
>>> abc.insert(10, 'koniec')
>>> abc
['raz', 'dva', 'tri', 'koniec']
>>> abc.insert(2, 'stred')
>>> abc
['raz', 'dva', 'stred', 'tri', 'koniec']
>>> abc.insert(0, 'zaciatok')
>>> abc
['zaciatok', 'raz', 'dva', 'stred', 'tri', 'koniec']
>>> abc.insert(-1, 'predposledny')
>>> abc
['zaciatok', 'raz', 'dva', 'stred', 'tri', 'predposledny', 'koniec']
Uvedomte si, že zoznam.insert(len(zoznam), hodnota)
pridáva vždy na koniec zoznamu, teda robí to isté ako zoznam.append(hodnota)
.
Napríklad:
>>> abc = ['raz', 'dva', 'tri', 'styri']
>>> abc.pop(7)
...
IndexError: pop index out of range
>>> abc.pop(-1) # to isté ako abc.pop()
'styri'
>>> abc.pop(0) # vyhadzuje prvý prvok
'raz'
>>> abc
['dva', 'tri']
>>> abc.pop(1)
'tri'
>>> abc.pop(0)
'dva'
>>> abc.pop(0)
...
IndexError: pop from empty list
>>> abc
[]
Posledné volanie metódy pop()
sa snaží vybrať prvý prvok z prázdneho zoznamu - spôsobilo to vyvolanie správy o chybe.
Napríklad:
>>> abc = ['raz', 'dva', 'tri', 'dva']
>>> abc.remove('dva')
>>> abc
['raz', 'tri', 'dva']
>>> abc.remove('styri')
...
ValueError: list.remove(x): x not in list
Napríklad:
>>> abc = ['raz', 'dva', 'tri', 'styri']
>>> abc.sort()
>>> abc
['dva', 'raz', 'styri', 'tri']
>>> post = list(reversed(range(10)))
>>> post
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> post.sort()
>>> post
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Častou začiatočníckou chybou býva priradenie výsledku tejto metódy (teda None
) do premennej, napríklad:
>>> abc = ['raz', 'dva', 'tri', 'styri']
>>> abc = abc.sort() # vždy vráti None
>>> print(abc)
None
Takto si pokazíme referenciu na pekne utriedený zoznam.
Zoznam ako výsledok funkcie¶
Prvá funkcia vráti novo vytvorený zoznam rovnakých hodnôt:
def urob_zoznam(n, hodnota=0):
return [hodnota] * n
Môžeme to použiť napríklad takto (premenné sme nazvali pole
, lebo sa to trochu podobá na pascalovské polia):
>>> pole1 = urob_zoznam(30)
>>> pole2 = urob_zoznam(25, None)
>>> pole3 = urob_zoznam(3, 'Python')
>>> pole1
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> pole2
[None, None, None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None, None, None,
None, None, None, None, None]
>>> pole3
['Python', 'Python', 'Python']
Ďalšia funkcia vytvorí z danej postupnosti nový zoznam:
def zoznam(postupnost):
vysl = []
for prvok in postupnost:
vysl.append(prvok)
return vysl
Uvedomte si, že to robí skoro to isté ako volanie funkcie list()
:
>>> py = zoznam('Python')
>>> py
['P', 'y', 't', 'h', 'o', 'n']
>>> cisla = zoznam(range(3, 25, 4))
>>> cisla
[3, 7, 11, 15, 19, 23]
Funkcia pridaj()
na základe nejakého zoznamu vytvorí nový zoznam, na koniec ktorého pridá nový prvok:
def pridaj(zoznam, hodnota):
return zoznam + [hodnota]
Všimnite si, že pôvodný zoznam pritom ostal nezmenený:
>>> zoz = ['raz', 'dva', 'tri']
>>> novy = pridaj(zoz, 'styri')
>>> novy
['raz', 'dva', 'tri', 'styri']
>>> zoz
['raz', 'dva', 'tri']
Takejto funkcii budeme hovoriť, že je immutable, lebo nemení hodnotu žiadneho predtým existujúceho zoznamu.
Ak by sme túto funkciu zapísali takto:
def pridaj1(zoznam, hodnota):
zoznam.append(hodnota)
return zoznam
Volaním tejto funkcie by sme dostali veľmi podobné výsledky:
>>> zoz = ['raz', 'dva', 'tri']
>>> novy = pridaj1(zoz, 'styri')
>>> novy
['raz', 'dva', 'tri', 'styri']
>>> zoz
['raz', 'dva', 'tri', 'styri']
Ale zmenila sa pritom aj hodnota prvého parametra - premennej zoz
typu zoznam. Táto funkcia je mutable - mení svoj parameter zoz
typu list
.
Dve premenné referencujú na ten istý zoznam¶
Už sme získali predstavu o tom, že priradenie zoznamu do premennej označuje, že sme v skutočnosti do premennej priradili referenciu na zoznam. Lenže na ten istý zoznam v pamäti môžeme mať viac referencií, napríklad:
>>> a = [2, 3, 5, 7, 11]
>>> b = a
>>> b[3] = 'kuk'
>>> a
[2, 3, 5, 'kuk', 11]
Menili sme obsah premennej b
(zmenili sme jej prvok s indexom 3), ale tým sa zmenil aj obsah premennej a
. Totiž obe premenné referencujú na ten istý zoznam:

Keď teraz meníme obsah premennej b
(ale len pomocou mutable operácií!), zmení sa aj obsah premennej a
:

Zhrňme¶
Vkladanie do zoznamu¶
Videli sme viac rôznych spôsobov, ako môžeme pridať jednu hodnotu do zoznamu. Vkladanie nejakej hodnoty
pred prvok s indexom i
:
pomocou rezu (mutable):
zoznam[i:i] = [hodnota]
pomocou metódy
insert()
(mutable):zoznam.insert(i, hodnota)
ak
i
==len(zoznam)
, pridávame na koniec (za posledný prvok), môžeme použiť metóduappend()
(mutable):zoznam.append(hodnota)
to isté dosiahneme aj takto (mutable):
zoznam += [hodnota]
Vo vašich programoch použijete ten zápis, ktorý sa vám bude najlepšie hodiť, ale zápis s rezom zoznam[i:i]
je najmenej čitateľný a používa sa veľmi zriedkavo.
zrejme funguje aj (immutable):
zoznam = zoznam[:i] + [hodnota] + zoznam[i:]
toto priradenie nemodifikuje pôvodný zoznam, ale vytvára nový s pridanou hodnotou
Vyhadzovanie zo zoznamu¶
Aj vyhadzovanie prvku zo zoznamu môžeme robiť viacerými spôsobmi. Ak vyhadzujeme prvok na indexe i
, môžeme zapísať:
pomocou rezu (mutable):
zoznam[i:i+1] = []
pomocou príkazu
del
(mutable):del zoznam[i]
pomocou metódy
pop()
, ktorá nám aj vráti vyhadzovanú hodnotu (mutable):hodnota = zoznam.pop(i)
veľmi neefektívne pomocou metódy
remove()
, ktorá ako parameter očakáva nie index ale vyhadzovanú hodnotu (mutable):zoznam.remove(zoznam[i])
tento spôsob je veľmi neefektívny (zbytočne sa hľadá prvok v zozname) a okrem toho niekedy môže vyhodiť nie
i
-ty prvok, ale prvok s rovnakou hodnotou, ktorý sa v zozname nachádza skôr, ako na indexei
.zrejme funguje aj (immutable):
zoznam = zoznam[:i] + zoznam[i+1:]
toto priradenie nemodifikuje pôvodný zoznam, ale vytvára nový bez prvku s daným indexom
Vyhodenie všetkých prvkov zo zoznamu¶
najjednoduchší spôsob (immutable):
zoznam = []
môžeme použiť len vtedy, keď nepotrebujeme uchovať referenciu na zoznam - toto priradenie nahradí momentálnu referenciu na zoznam referenciou na úplne nový zoznam; ak to použijeme vo vnútri funkcie, stratí sa tým referencia na pôvodný zoznam
Ďalšie spôsoby uchovávajú referenciu na zoznam:
všetky prvky zoznamu postupne vyhodíme pomocou while-cyklu (mutable):
while zoznam: zoznam.pop()
toto je zbytočne veľmi neefektívne riešenie
priradením do rezu (mutable):
zoznam[:] = []
je ťažšie čitateľné a menej pochopiteľné riešenie
metódou
clear()
(mutable):zoznam.clear()
je asi najčitateľnejší zápis
Vytvorenie kópie zoznamu¶
Ak potrebujeme vyrobiť kópiu celého zoznamu, dá sa to urobiť:
pomocou cyklu:
kopia = [] for prvok in zoznam: kopia.append(prvok)
môžeme využiť aj rez:
kopia = zoznam[:]
keďže funguje funkcia
list()
, môžeme zapísať:kopia = list(zoznam)
Cvičenia¶
Napíš funkciu
vypis_typy(zoznam)
, ktorá vypíše všetky prvky zoznamu a ku každému vypíše informáciu o jeho type: ak je toint
alebofloat
, tak vypíše'číslo'
; ak je tostr
, tak vypíše'reťazec'
; inak všetky ostatné typy vypíše ako'iný typ'
. Napríklad:>>> vypis_typy([12, 'x', None, 3.14, [], range(5), '123']) 12 - číslo x - reťazec None - iný typ 3.14 - číslo [] - iný typ range(0, 5) - iný typ 123 - reťazec
Môžeš využiť takýto test:
if type(prvok) == str: ...
.
Napíš funkciu
nakup(zoznam)
, ktorá spracuje nákupný zoznam a vráti jeho celkovú cenu. Vstupný zoznam obsahuje dvojice čísel v tvare[koľko, cena, koľko, cena, ...]
, ktorý pre každý nakúpený tovar označuje jeho množstvo (koľko
) a jednotkovú cenu (cena
). Napríklad:>>> cena = nakup([3, 2.5, 0.5, 10, 1.2, 1.2]) >>> cena 13.94
Napíš funkciu
sucin(zoznam)
, ktorá vráti (return
) súčin prvkov zoznamu (zoznam obsahuje len čísla). Ak je zoznam prázdny, funkcia vráti1
. Napríklad:>>> c = [2, 3, 5, 7, 11] >>> sucin(c) # čo je 2*3*5*7*11 2310 >>> sucin(list(range(1, 11))) # čo je 10 faktorial 3628800 >>> sucin([2] * 20) # čo je 2 ** 20 1048576
Napíš funkciu
vypis(zoznam, pocet=1)
, ktorá prvky daného zoznamu vypíše tak, že v každom riadku (možno okrem posledného) vypíše presne zadanýpocet
prvkov zoznamu. Funkcia nemodifikuje vstupnýzoznam
. Napríklad:>>> zoz = list(range(1, 19)) >>> vypis(zoz, 4) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 >>> zoz [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18] >>> vypis(list('Python'), 2) P y t h o n >>> vypis(['prvy', 'druhy', 'treti']) prvy druhy treti >>>
Napíš funkciu
spoj(zoznam, retazec='')
, ktorá z daného zoznamu hodnôt (čísel alebo reťazcov) vyrobí jeden reťazec, ktorý obsahuje všetky prvky zoznamu, pričom medzi tieto hodnoty vloží zadanýretazec
. Napríklad:>>> spoj(['12', 3, '456', '7'], '+') '12+3+456+7' >>> spoj(['12', 3, '456', 7], ' <=> ') '12 <=> 3 <=> 456 <=> 7' >>> spoj([], '*') '' >>> spoj(list('python'), '*') 'p*y*t*h*o*n' >>> spoj(list(range(11, 20))) '111213141516171819'
Napíš funkciu
zacina(zoznam, zacina_retazcom)
, ktorá vráti zoznam tých prvkov, ktoré začínajú zadaným podreťazcom. Vstupný zoznam obsahuje len znakové reťazce. Napríklad:>>> m = ['hela', 'adam', 'boris', 'adela', 'bobo', 'miso', 'hektor', 'borka', 'mino'] >>> zacina(m, 'mi') ['miso', 'mino'] >>> print(zacina(m, 'bor')) ['boris', 'borka'] >>> print(zacina(m, 'b')) ['boris', 'bobo', 'borka']
Napíš funkciu
zostupne(zoznam)
, ktorá zistí, či sú prvky vstupného zoznamu usporiadané zostupne (každý prvok v zozname nie je väčší ako jeho predchádzajúci). Funkcia vráti (return
)True
aleboFalse
, nemodifikuje vstupnýzoznam
a nič nevypisuje. Nepoužívajsort
anisorted
. Napríklad:>>> zostupne([5, 5, 4, 4, 4, 2, 1]) True >>> zostupne([5, 5, 4, 4, 1, 2, 1]) False >>> zostupne(['zu', 'ta', 'si', 'mu', 'el']) True
Napíš funkciu
postupnost(start, koniec, krok=1)
, ktorá vytvorí (vráti) takýto zoznam čísel: jeho prvky sú hodnoty odstart
dokoniec
krokomkrok
(podobne akorange(start, koniec, krok)
, ale funkciapostupnost
by mohla fungovať aj pre desatinné čísla). Nepouži pritom štandardnú funkciurange()
. Napríklad:>>> postupnost(3, 100, 7) [3, 10, 17, 24, 31, 38, 45, 52, 59, 66, 73, 80, 87, 94] >>> postupnost(20, 0, -2) [20, 18, 16, 14, 12, 10, 8, 6, 4, 2] >>> postupnost(1, 5, 0) [] >>> postupnost(0, 3, 0.5) [0, 0.5, 1.0, 1.5, 2.0, 2.5]
Napíš funkciu
sucet(zoznam1, zoznam2)
, ktorá sčíta/zlepí dva zoznamy čísel/reťazcov po prvkoch. Tieto zoznamy môžu byť rôzne dlhé. Napríklad:>>> sucet([1, 20, 3, 40], [10, 2, 30, 4]) [11, 22, 33, 44] >>> sucet([2, 3, 4, 5, 6, 7], [10, 20, 30]) [12, 23, 34, 5, 6, 7] >>> sucet([], [2, 3, 5, 7]) [2, 3, 5, 7] >>> sucet(['1.', '2.', '3.', '4.'], list('python')) ['1.p', '2.y', '3.t', '4.h', 'o', 'n']
Napíš funkciu
kresli_kruhy(zoznam, r)
, ktorá z daného zoznamu farieb nakreslí rad farebných kruhov, Každý kruh má polomerr
. Funkcia nemodifikuje vstupnýzoznam
. Napríklad:import tkinter def kresli_kruhy(zoznam, r): ... canvas = tkinter.Canvas() canvas.pack() kresli_kruhy(['red', 'red', 'blue', 'orange', 'green', 'yellow'], 20) tkinter.mainloop()
nakreslí:
Napíš funkciu
kresli_stvorce(zoznam)
, ktorá z daného zoznamu čísel (veľkostí) a farieb nakreslí rad farebných štvorcov, Funkcia nemodifikuje vstupnýzoznam
. Napríklad:import tkinter def kresli_stvorce(zoznam): ... canvas = tkinter.Canvas() canvas.pack() kresli_stvorce([50, 'red', 100, 'blue', 70, 'yellow', 120, 'pink']) tkinter.mainloop()
nakreslí:
Napíš najprv funkciu
nahodny_zoznam(n, od, do)
, ktorá vygenerujen
-prvkový zoznam náhodných čísel z ontervalu<od, do>
. Potom napíš ďalšiu funkciuhistogram(zoznam)
, ktorá z daného zoznamu čísel (môže byť vygenerovaný pomocounahodny_zoznam(...)
) nakreslí stĺpcový diagram (obdĺžniky rovnakej šírky a výšky podľa číselnej hodnoty zo zoznamu). Obdĺžniky budú mať takú šírku, aby čo najlepšie vyplnili šírku plochy360
a budú mať náhodne zafarbenú výplň. Funkcia nemodifikuje vstupnýzoznam
. Môžeš počítať s tým, že všetky hodnoty v zozname nie sú väčšie ako240
. Napríklad:import tkinter import random def nahodny_zoznam(n, od, do): ... def histogram(zoznam): ... canvas = tkinter.Canvas() canvas.pack() zoz = nahodny_zoznam(20, 10, 240) print(zoz) histogram(zoz) tkinter.mainloop()
môže vypísať:
[113, 107, 103, 192, 203, 141, 77, 72, 84, 126, 106, 220, 47, 28, 170, 237, 100, 105, 218, 12]
a nakresliť:
Napíš funkciu
kresli_polygon(zoznam_x, zoznam_y)
, ktorá dostáva dva rovnakodlhé zoznamy čísel - tieto obsahujú postupnosti x-ových a y-ových súradníc bodov v grafickej ploche. Aby sme z týchto bodov mohli nakresliť polygon, treba z týchto dvoch zoznamov vytvoriť jeden, v korom sa budú striedať príslušné x-ové a y-ové súradnice. Funkcia potom nakreslí polygón s náhodne zafarbenou výplňou. Napríklad:import tkinter import random def kresli_polygon(zoznam_x, zoznam_y): ... canvas = tkinter.Canvas() canvas.pack() kresli_polygon([50, 150, 120, 60, 220], [10, 50, 200, 120, 150]) tkinter.mainloop()
nakreslí:
Ak využijeme funkciu
nahodny_zoznam(...)
z predchádzajúcej úlohy, môže to vyzerať napríklad takto:kresli_polygon(nahodny_zoznam(20, 10, 360), nahodny_zoznam(20, 10, 250))
Napíš funkciu
replace_novy(zoznam, co, zaco)
, ktorá vráti nový zoznam: v tomto novom zozname budú všetky prvky s hodnotouco
nahradené hodnotouzaco
. Ostatné prvy sa prekopírujú. Napríklad:>>> zoz = [12, 13, 14, 13, 11, 14, 15, 13] >>> novy = replace_novy(zoz, 13, 'x') >>> novy [12, 'x', 14, 'x', 11, 14, 15, 'x'] >>> zoz [12, 13, 14, 13, 11, 14, 15, 13] >>> replace_novy([1, 2] * 10, 1, 9) [9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2]
Napíš funkciu
replace(zoznam, co, zaco)
, ktorá v danom zozname všetky výskyty hodnotyco
nahradí hodnotouzaco
. Funkcia nič nevracia ani nevypisuje, len modifikuje obsah zoznamu. Napríklad:>>> zoz = [12, 13, 14, 13, 11, 14, 15, 13] >>> replace(zoz, 13, 'x') >>> zoz [12, 'x', 14, 'x', 11, 14, 15, 'x'] >>> zoz = [1, 2] * 10 >>> replace(zoz, 1, 9) >>> zoz [9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2]
Napíš funkciu
dvojice(zoznam)
, ktorá v danom zozname spočíta (alebo zreťazí) dvojice prvkov. Teda spočíta/zreťazí (operácia+
) prvý a druhý prvok a oba nahradí týmto súčtom, potom to isté s tretím a štvrtým, potom piatym a šiestym, atď. Funkcia nič nevracia ani nevypisuje, len modifikuje obsah zoznamu. Napríklad:>>> z = list('programovanie') >>> dvojice(z) >>> z ['pr', 'og', 'ra', 'mo', 'va', 'ni', 'e'] >>> z = list(range(1, 11)) >>> z [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> dvojice(z) >>> z [3, 7, 11, 15, 19] >>> dvojice(z) >>> z [10, 26, 19]
Napíš funkciu
fibonacci(zoznam, n)
, ktorá dostáva nejaký aspoň dvojprvkový zoznam čísel. Do tohto zoznamu pridá ďalšíchn
čísel tak, že každé je súčtom dvoch predchádzajúcich. VFunkcia nič nevracia, len modifikuje vstupný zoznam. Napríklad:>>> zoz = [0, 1] >>> fibonacci(zoz, 10) >>> zoz [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] >>> fibonacci(zoz, 5) >>> zoz [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987] >>> zoz = [0, -2] >>> fibonacci(zoz, 10) >>> zoz [0, -2, -2, -4, -6, -10, -16, -26, -42, -68, -110, -178]
Napíš funkciu
rozklad(cislo)
, ktorá rozloží dané celé číslocislo
na prvočinitele (súčin prvočísel). Výsledkom funkcie bude zoznam týchto prvočísel (prvočiniteľov). Funkcia nič nevypisuje. Napríklad:>>> r = rozklad(478632) >>> r [2, 2, 2, 3, 7, 7, 11, 37] >>> rozklad(43) [43]
Zrejme, ak by sme použili funkciu
sucin(...)
z 3. úlohy, mohli by sme skontrolovať správnosť funkcierozklad
:>>> sucin(rozklad(478632)) 478632
Napíš funkciu
zoznam_cifier(cislo)
, ktorá z daného nezáporného celého čísla vytvorí zoznam jeho cifier. Funkcia nič nevypisuje, len vráti (return
) nejaký zoznam čísel. Napríklad:>>> zoznam_cifier(478632) [4, 7, 8, 6, 3, 2] >>> zoznam_cifier(111111111 ** 2) [1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]
Napíš funkciu
cislo_zo_zoznamu(zoznam)
, ktorá z daného zoznamu cifier (jednociferné celé čísla) poskladá pôvodné celé číslo (obrátená funkcia kzoznam_cifier()
). Funkcia nič nevypisuje, len vráti (return
) nejaké číslo. Napríklad:>>> cislo_zo_zoznamu(list(range(1, 10))) 123456789 >>> cislo_zo_zoznamu(zoznam_cifier(2 ** 20)) 1048576
Napíš funkciu
citaj_cisla(meno_suboru)
, ktorá prečíta daný textový súbor. V tomto súbore sa v každom riadku nachádza jedno celé číslo, prípadne nejaké medzery na začiatku a na konci. Funkcia vráti zoznam týchto celých čísel. Funkcia nič nevypisuje, len vráti (return
) nejaký zoznam čísel. Napríklad:>>> print('123\n 45\n 678 \n-9 ', file=open('cisla.txt', 'w')) >>> citaj_cisla('cisla.txt') [123, 45, 678, -9]
Napíš funkciu
prevrat(meno_suboru)
, ktorá prevráti poradie riadkov v danom textovom súbore. Funkcia nič nevypisuje ani nevracia, len zmení obsah zadaného textového súboru. Napríklad:>>> print('prvy\n druhy\n treti\nstvrty', file=open('text.txt', 'w')) >>> prevrat('text.txt') >>> print(open('text.txt').read(), end='') stvrty treti druhy prvy >>>
Napíš funkciu
stvorec(x, y, r, uhol)
, ktorá vytvorí (vráti) 8-prvkový zoznam čísel v tvare [x, y, x, y, x, y, x, y]. Tieto čísla sú súradnicami štyroch vrcholov štvorca v grafickej ploche a tieto vrcholy ležia na kružnici so stredom(x, y)
s polomeromr
. Vrcholy štvorca budú na kružnici natočené o danýuhol
. Ak by si tento zoznam poslal ako parameter do grafického príkazucanvas.create_polygon
, dostaneš vyfarbený natočený štvorec. Napríklad:import tkinter from math import sin, cos, radians def stvorec(x, y, r, uhol): ... canvas = tkinter.Canvas() canvas.pack() canvas.create_polygon(stvorec(180, 130, 110, 20), fill='red') canvas.create_polygon(stvorec(180, 130, 90, 45), fill='green') canvas.create_polygon(stvorec(180, 130, 70, 70), fill='gold') canvas.create_polygon(stvorec(180, 130, 50, 95), fill='blue') tkinter.mainloop()
nakreslí:
4. Týždenný projekt¶
Napíš pythonovský skript, ktorý bude definovať túto funkciu:
vypis(meno_suboru, sirka, zarovnat=True, slovo='')
Funkcia vypis()
dostáva ako prvý parameter meno textového súboru a druhým parametrom je celé číslo, ktoré udáva šírku výpisu. Funkcia tento súbor prečíta a celý ho vypíše do textovej plochy (do konzoly) tak, že bude zarovnaný na danú šírku.
Textový súbor sa skladá z odsekov, ktoré sa skladajú zo slov. Odseky sú navzájom oddelené aspoň jedným prázdnym riadkom. Slová v odseku sú navzájom oddelené aspoň jednou medzerou alebo koncom riadka.
Napríklad, "subor1.txt"
sa skladá z týchto riadkov:
Ján Botto:
Žltá ľalija
Stojí, stojí mohyla.
Na mohyle zlá chvíľa,
na mohyle tŕnie, chrastie
a v tom tŕní, chrastí rastie,
rastie, kvety rozvíja
jedna žltá ľalija.
Tá ľalija smutno vzdychá:
Hlávku moju tŕnie pichá
a nožičky oheň páli —
pomôžte mi v mojom žiali!
Tento súbor obsahuje 5 „odsekov“, pričom najkratší je druhý a má 3 „slová“. Najdlhší je tretí odsek má 20 slov.
Volanie vypis('subor1.txt', 20)
vypíše:
Ján Botto: Žltá
ľalija
Stojí, stojí mohyla.
Na mohyle zlá
chvíľa, na mohyle
tŕnie, chrastie a v
tom tŕní, chrastí
rastie, rastie,
kvety rozvíja jedna
žltá ľalija.
Tá ľalija smutno
vzdychá:
Hlávku moju tŕnie
pichá a nožičky oheň
páli — pomôžte mi v
mojom žiali!
Pričom vypis('subor1.txt', 60)
vypíše:
Ján Botto: Žltá ľalija
Stojí, stojí mohyla.
Na mohyle zlá chvíľa, na mohyle tŕnie, chrastie a v tom
tŕní, chrastí rastie, rastie, kvety rozvíja jedna žltá
ľalija.
Tá ľalija smutno vzdychá:
Hlávku moju tŕnie pichá a nožičky oheň páli — pomôžte mi v
mojom žiali!
Všimni si, že všetky riadky v odseku okrem posledného sú zarovnané vpravo na zadanú šírku, pričom, ak by bola dĺžka takéhoto riadka kratšia ako zadaná šírka, medzi slová sú rovnomerne vložené medzery. Ak nejaký riadok obsahuje len jedno slovo, tak ani tento sa nezarovnáva na pravý okraj. Ak je nejaké slovo dlhšie ako zadaná šírka, tak toto slovo sa nerozdeľuje do viacerých riadkov, ale bude v riadku výpisu jediné.
Funkcia vypis()
má ešte ďalšie dva parametre, ktoré majú určené aj náhradné hodnoty:
parameter
zarovnat
s hodnotouTrue
pracuje tak, ako bolo popísané vyššie, teda všetky riadky všetkých odsekov (okrem posledných a jednoslovných) zarovnáva na pravý okraj. HodnotaFalse
označuje, že odseky sa na pravý okraj nezarovnávajú, ale text ostáva „zubatý“. Napríklad, volanievypis('subor1.txt', 45, False)
vypíše:
Ján Botto: Žltá ľalija
Stojí, stojí mohyla.
Na mohyle zlá chvíľa, na mohyle tŕnie,
chrastie a v tom tŕní, chrastí rastie,
rastie, kvety rozvíja jedna žltá ľalija.
Tá ľalija smutno vzdychá:
Hlávku moju tŕnie pichá a nožičky oheň páli —
pomôžte mi v mojom žiali!
ďalší parameter
slovo
s hodnotou''
označuje, že treba spracovať (zarovnať, alebo nezarovnať) všetky odseky v súbore. Iná hodnota označuje, že chceme spracovávať len tie odseky, ktoré obsahujú toto konkrétne slovo. Napríklad, volanievypis('subor1.txt', 45, True, 'kvety')
vypíše len tento jeden odsek:
Na mohyle zlá chvíľa, na mohyle tŕnie,
chrastie a v tom tŕní, chrastí rastie,
rastie, kvety rozvíja jedna žltá ľalija.
Tvoj odovzdaný program s menom riesenie.py
musí začínať tromi riadkami komentárov (s tvojim menom a dátumom):
# 4. zadanie: zarovnaj
# autor: Janko Hraško
# datum: 17.10.2022
Projekt riesenie.py
odovzdávaj na úlohový server https://list.fmph.uniba.sk/. Testovač bude spúšťať tvoju funkciu s rôznymi textovými súbormi, ktoré si môžeš stiahnuť z L.I.S.T.u. Môžeš zaň získať 5 bodov.