Uživatelské nástroje

Nástroje pro tento web


prog:list2

Seznamy - pokračování

Možnosti seznamů jsme dosud rozhodně nevyčerpali, bez řady níže popsaných věcí bychom se v praxi jen těžko obešli.

Úpravy seznamů

Dosavadní výklad týkající se seznamů byl do značné míry založen na analogiích s textovými řetězci. Nyní se zaměříme na možnosti principiálně nové - přímé úpravy seznamů.

Pomocí indexovacího operátoru můžeme kromě čtení také měnit konkrétní prvky seznamu nebo dokonce celé řezy. Takové možnosti u řetězců nemáme.

jmena = ["Jan", "Petra", "Jakub", "Marie"]
 
# práce s jedním prvkem seznamu
jmena[2]                 # => 'Jakub' (to není nic nového)
jmena[2] = "Pavel"       # změna prvku s indexem 2 (přiřazení nové hodnoty)
jmena                    # => ['Jan', 'Petra', 'Pavel', 'Marie']
 
# práce s řezem (podseznamem)
jmena[1:3]               # => ['Petra', 'Pavel'] (opět známá záležitost)
jmena[1:3] = ["Tereza", "David"]       # nahradíme řez jiným seznamem
jmena                    # => ['Jan', 'Tereza', 'David', 'Marie']
jmena[0:2] = ["Karel", "Aneta", "Jana", "Josef"]
           # nahrazení řezu seznamem jiné délky (změna počtu prvků seznamu)
jmena      # => ['Karel', 'Aneta', 'Jana', 'Josef', 'David', 'Marie']
jmena[2:4] = []          # nahrazení řezu prázdným seznamem (tj. vymazání)
jmena                    # => ['Karel', 'Aneta', 'David', 'Marie']

Seznamy lze měnit také pomocí některých metod.

cisla = [14, 2, -5, 8]
 
# přidání prvku na konec seznamu
cisla.append(11)
cisla                    # => [14, 2, -5, 8, 11]
# připojení seznamu na konec
cisla.extend([0, -4])
cisla                    # => [14, 2, -5, 8, 11, 0, -4]
cisla += [2, 3]          # jiný způsob zápisu pro stejnou činnost
cisla                    # => [14, 2, -5, 8, 11, 0, -4, 2, 3]
 
# odstranění prvku na konci seznamu
cisla.pop()              # => 3 (je vrácena hodnota mazaného prvku)
cisla                    # => [14, 2, -5, 8, 11, 0, -4, 2]
# odstranění prvku na určené pozici (dané indexem)
cisla.pop(3)             # => 8 (opět vrací hodnotu prvku)
cisla                    # => [14, 2, -5, 11, 0, -4, 2]
 
# vložení nového prvku na určenou pozici
cisla.insert(2, 10)      # na pozici s indexem 2 je vložen nový prvek
cisla                    # => [14, 2, 10, -5, 11, 0, -4, 2]
 
# vymazání prvku s určenou hodnotou
cisla.remove(2)          # první prvek s hodnotou 2 je vymazán
cisla                    # => [14, 10, -5, 11, 0, -4, 2]
cisla.remove(20)         # => chyba ValueError, protože prvek 20 neexistuje

Minimum, maximum a součet

Při práci se seznamy, jejichž prvky lze porovnávat1) (typicky pole čísel nebo řetězců) můžeme pomocí funkcí min a max určit hodnotu nejmenšího a největšího prvku seznamu.

min([12.1, -3.1, 5.04, 6, 0.215])           # => -3.1
max(["haf", "kokodák", "bůů", "mňau"])      # => 'mňau'

O problematice řazení řetězců jsme již hovořili. Není překvapivé, že použití funkcí min a max na prázdný seznam skončí chybou (ValueError), stejně tak chybou (TypeError) skončí pokus o porovnání prvků nekompatibilních typů, např. pro seznam s prvky typu int a zároveň str.

Pro seznam složený pouze z číselných prvků můžeme snadno určit součet všech jeho prvků funkcí sum, součet prázdného seznamu je samozřejmě 0.

sum([1, 2, 3, 4, 5, 6])                     # => 21
sum([0.25, -1.08, 1, 0, 0.15])              # => 0.31999999999999995

Porovnávání seznamů

Seznamy je obecně možné také porovnávat. Postupuje se přitom dle podobného principu jako u řetězců - porovnávají se postupně od začátku odpovídající prvky než se narazí na rozdíl nebo je některý seznam vyčerpán (tzv. lexikografického uspořádání). Z toho mj. plyne, že odpovídající prvky musí být porovnatelné.

[1, 2, 3] < [1, 3, 5]    # => True (rozdíl ve 2. prvku)
[1, "aa"] < [1, "ab"]    # => True (odpovídající prvky stejných typů)
[] < [-1, 0, 1]          # => True (prázdný seznam je vždy menší)
[1, 2] < [1, 2, 3]       # => True (vyčerpání seznamu vlevo)
[1, 2, 3] < [2]          # => True (rozdíl již v 1. prvku)
[1, 2, 3] < [2, "A"]     # => True (na porovnání 2. prvků vůbec nedojde)
[1, 2, 3] < [1, "A"]     # chyba 'TypeError' při porovnání 2. prvků

Generátorová notace

V praxi často potřebujeme vytvořit seznam s prvky, které jsou vytvořeny podle nějakého pravidla (např. druhé mocniny prvních pěti přirozených čísel). To bychom s již nabytými znalostmi pomocí jednoduchého cyklu dokázali, ale Python nám pomocí tzv. generátorové notace (anglicky list comprehension) dává elegantní možnost zkráceného zápisu. Místo

ctverce = []
for i in range(1, 6):
    ctverce.append(i * i)

tak můžeme zapsat

ctverce = [i * i for i in range(1, 6)]

se stejným výsledkem [1, 4, 9, 16, 25]. Zápis je kratší a přitom dobře srozumitelný. Skládá se z nějakého cyklu (v našem případě for i in range(1, 6)), před nímž stojí požadovaná operace s řídicí proměnnou cyklu (v našem případě i * i) a nepovinně může být zakončen ještě nějakou podmínkou (jak uvidíme v následujících případech).

# přirozená čísla menší než 6
[i for i in range(1, 6)]                # => [1, 2, 3, 4, 5]
# lichá čísla menší než 10
[i for i in range(1, 10, 2)]            # => [1, 3, 5, 7, 9]
# čísla od 0 po 1/10 menší než 0.5
[0.1 * i for i in range(5)]
               # => [0.0, 0.1, 0.2, 0.30000000000000004, 0.4]
# vzdálenosti od 0 do 0.5 m jako řetězce na 2 des. místa s jednotkou
["{:.2f} m".format(0.1 * i) for i in range(5)]  
               # => ['0.00 m', '0.10 m', '0.20 m', '0.30 m', '0.40 m']
 
# pomocí podmínky za 'if' lze hodnoty omezit
# přirozená čísla, která jsou dělitelná 3 nebo 5
[i for i in range(1, 30) if i % 3 == 0 or i % 5 == 0]
               # => [3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24, 25, 27]
# kódy řídicích znaků (ASCII 0 až 31), které jsou pokládány za "bílé"
[i for i in range(32) if chr(i).isspace()]
               # => [9, 10, 11, 12, 13, 28, 29, 30, 31]

V generátorové notaci může být použit i více než jeden cyklus (což odpovídá použití vnořených cyklů).

# dvojciferná čísla, na pozici desítek 3 nebo 5, jednotky 1, 3 nebo 7
[10 * i + j for i in [3, 5] for j in [1, 3, 7]]
               # => [31, 33, 37, 51, 53, 57]
# seznam všech 64 polí šachovnice
[i + str(j) for i in "abcdefgh" for j in range(1, 9)]               
               # => ['a1', 'a2', 'a3', 'a4', ..., 'h6', 'h7', 'h8']

Možná si vzpomenete, že jsme v jedné úloze hledali trojciferná čísla taková, že součet třetích mocnin jejich číslic je roven tomuto číslu. Pomocí generátorové notace lze i tento seznam přímo vytvořit.

[i for i in range(100, 1000) if (i//100)**3+(i%100//10)**3+(i%10)**3 == i]
               # => [153, 370, 371, 407]

Proměnné použité v rámci generátorové notace v cyklech uvnitř hranatých závorek se chovají podobně jako lokální proměnné ve funkcích, tj. nijak nemění hodnoty případných jiných proměnných stejného jména mimo hranaté závorky.

1)
tj. určit větší/stejný pomocí relačních operátorů
prog/list2.txt · Poslední úprava: 02.04.2018 12:54 autor: Ivana Stefanová

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki