Aktuálně: Postihly zákazy tvou profesi? Poptávka po ajťácích prudce roste, využij podzimní akce 30% výuky zdarma!
Pouze tento týden sleva až 80 % na e-learning týkající se JavaScript
JavaScript týden

Lekce 9 - Vícerozměrná pole v Pythonu

V minulé lekci, Funkce a výjimky v Pythonu, jsme se podívali na textové řetězcích. Dnešní tutoriál je v sekci základních konstrukcí Pythonu v podstatě bonusový a pojednává o tzv. vícerozměrných polích. Teoreticky můžete rovnou přejít k objektově orientovanému programování, doporučuji však si konec této sekce ještě alespoň projít, abyste měli o zbývajících technikách povědomí. Přeci jen se jedná o dosti základní vědomosti.

Již umíme pracovat s jednorozměrným polem, které si můžeme představit jako řádku přihrádek v paměti počítače.

Pole

(Na obrázku je vidět pole osmi čísel)

Ačkoli to není tak časté, v programování se občas setkáváme i s vícerozměrnými poli a to zejména pokud programujeme nějakou simulaci (např. hru).

Pole polí

Python vlastně vícerozměrná pole nepodporuje. Můžeme si v nich ale stejně vytvořit kolika-rozměrné pole chceme, jelikož 2D pole není vnitřně nic jiného, než pole polí. Situaci si můžeme představit tak, že si vytvoříme pole o pěti prvcích (1. řádek) a každá buňka v tomto řádku v sobě bude obsahovat další pole, reprezentující sloupeček.

Dvourozměrné pole

Dvourozměrné pole si můžeme v paměti představit jako tabulku a mohli bychom takto reprezentovat např. rozehranou partii piškvorek. Pokud bychom se chtěli držet reálných aplikací, které budete později v zaměstnání tvořit, můžeme si představit, že do 2D pole budeme ukládat informace o obsazenostech sedadel v kinosálu. Situaci bychom si mohli graficky znázornit např. takto:

2D pole

(Na obrázku je vidět 2d pole reprezentující obsazenost kinosálu)

Kinosál by byl v praxi samozřejmě větší, ale jako ukázka nám toto pole postačí. 0 znamená volno, 1 obsazeno. Později bychom mohli doplnit i 2 - rezervováno a podobně. Pro tyto stavy by bylo správnější vytvořit si vlastní datový typ, tzv. výčet (Enum), ale s ním se setkáme až později, takže si teď musíme vystačit pouze s čísly.

2D pole vytvoříme v Pythonu následujícím způsobem:

kinosal = []

for i in range(5):
    temp = []
    for j in range(5):
        temp.append(0)
    kinosal.append(temp)
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Napřed si vytvoříme prázdný seznam. Poté v prvním cyklu vytvoříme dočasný seznam temp, který postupně naplníme hodnotami a pak ho 5x přidáme do seznamu. Sami si musíme určit, jakými hodnotami budeme seznam naplňovat, v našem případě samými nulami.

Naplnění daty

Nyní kinosál naplníme jedničkami tak, jak je vidět na obrázku výše. Protože budeme jako správní programátoři líní, využijeme k vytvoření řádku jedniček for..in cykly :) Pro přístup k prvku 2D pole musíme samozřejmě zadat 2 souřadnice. První souřadnice je řádek a druhá je sloupec.

# Prostředek
kinosal[2][2] = 1
# 4. řádek
for i in range(1, 4):
    kinosal[3][i] = 1
# Poslední řádek
for j in range(0, 5):
    kinosal[4][j] = 1

Výpis

Výpis pole opět provedeme pomocí cyklu, na 2d pole budeme potřebovat cykly 2 (jeden nám proiteruje sloupce a druhý řádky). Procházet pole můžeme jednoduše cyklem for..in. Nebo můžeme použít i "složitější" způsoby, pokud chceme získat i indexy. Například range(len(seznam)) nebo funkci enumerate().

Cykly zanoříme do sebe tak, aby nám vnější cyklus projížděl řádky a vnitřní sloupce v aktuálním řádku. Po výpisu řádku je nutné odřádkovat. Oba cykly musí mít samozřejmě jinou řídící proměnnou:

for seznam in kinosal:
    for prvek in seznam:
        print(prvek, end="")
    print(end="\n")

Výsledek:

Konzolová aplikace
00000
00000
00100
01110
11111

N-rozměrná pole

Někdy může být příhodné vytvořit si pole o ještě více dimenzích. My všichni si jistě dokážeme představit minimálně 3D pole. S příkladem s kinosálem se nabízí případ užití, kdy má budova více pater (nebo obecně více kinosálů). Vizualizace by vypadala asi nějak takto:

3D pole

3D pole můžeme vytvořit tím samým způsobem, jako 2D pole, ale více komplikovaněji:

kinosaly = []

for i in range(3):
    kinosal = []
    for j in range(5):
        temp = []
        for k in range(5):
            temp.append(0)
        kinosal.append(temp)
    kinosaly.append(kinosal)

Kód výše vytvoří 3D pole jako na obrázku. Přistupovat k němu budeme opět přes indexy (hranaté závorky) jako předtím, jen již musíme zadat 3 souřadnice.

kinosaly[3][2][1] = 1

Zkrácená inicializace

Ještě si ukážeme, že i vícerozměrná pole je možné rovnou inicializovat hodnotami (kód vytvoří rovnou zaplněný kinosál jako na obrázku:

kinosal = [[0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0],
           [0, 0, 1, 0, 0],
           [0, 1, 1, 1, 0],
           [1, 1, 1, 1, 1]]

Zubatá pole

V některých případech nemusíme "plýtvat" pamětí na celou tabulku a můžeme pole vytvořit "zubaté" (anglicky jagged):

Pole polí

Nevýhodou tohoto přístupu je, že musíme pole nepříjemně inicializovat sami. Původní řádek s pěti buňkami sice existuje, ale jednotlivé sloupečky si do něj musíme navkládat sami:

zubate = [[15, 2, 8, 5, 3],
           [3, 3, 7],
           [9, 1, 16, 13],
           [],
           [5]]

A jeho vypsání:

for seznam in zubate:
    for prvek in seznam:
        print(prvek, end=" ")
    print(end="\n")

Na závěr bych rád dodal, že někteří lidé, kteří neumí správně používat objekty, využívají 2D polí k ukládání více údajů o jediné entitě. Např. budeme chtít uložit výšku, šířku a délku pěti mobilních telefonů. Ačkoli se vám nyní může zdát, že se jedná o úlohu na 3D pole, ve skutečnosti se jedná o úlohu na obyčejné 1D pole (přesněji seznam) objektů typu Telefon. Ale o tom až u objektově orientovaného programování. Pole si můžete vyzkoušet ještě v cvičení v této sekci.

V příští lekci, Knihovny math a random, se podíváme na matematické funkce.


 

Stáhnout

Staženo 158x (946 B)
Aplikace je včetně zdrojových kódů v jazyce python

 

Předchozí článek
Funkce a výjimky v Pythonu
Všechny články v sekci
Základní konstrukce jazyka Python
Článek pro vás napsal gcx11
Avatar
Jak se ti líbí článek?
12 hlasů
(^_^)
Aktivity (10)

 

 

Komentáře
Zobrazit starší komentáře (10)

Avatar
Milan Šmídl:30.12.2015 10:24
print("milduv fraktal")
import turtle#graficke prostredi, turtle se ovlada jednoduchymi prikazy forward atd.
initial = int(input("zadej základní rozmer"))#

def main():
    turtle.forward(initial)#
    turtle.left(90)
    while True:
           turtle.forward(lengh_computation)
           turtle.penup
           turtle.left(180)
           turtle.forward(lengh_computation)
           urtle.pendown
           turtle.forward(lengh_computation)


def lengh_computation(initial):
    while True:
        initial = initial/2
        return initial

Zde jsou dvě funkce a já bych to rád udělal tak, aby se pri každém cyklu (while ve funkci main)vzdálenost pohybu forward zmenšila o polovinu..Výpočet je ve funkci lengh...Jde o to jak se synchronizuji oba cykly, v podstatě bych si přál aby se pro každý cyklus ve funkci main provedl jeden cyklus výpočtu funkce lengh...
zkusil jsem už všemožné kombinace, ruzně jsem si to vyprintovával, ale asi jsem se nějak zacyklil...pokud jsi z toho alespoň trošku moudrý, tak budu opravdu velmi rád za jakýkoliv feedback...měj se pěkně

Editováno 30.12.2015 10:26
 
Odpovědět
30.12.2015 10:24
Avatar
Odpovídá na Milan Šmídl
Milan Šmídl:30.12.2015 10:33

Ps: je mi jasný, že v této podobě to nemůže chodit, je to pouze pro ilustraci co bych jakože rád udělal, zkoušel jsem třeba dvě funkce, kdy výstup jedné je vstupem druhe a naopak a funguji v cyclu, ale neúspěšně..V podstatě nic nefungovalo a už mě to dost flustruje:)

 
Odpovědět
30.12.2015 10:33
Avatar
coells
Redaktor
Avatar
Odpovídá na Milan Šmídl
coells:30.12.2015 11:43

Fraktály je jednodušší psát pomocí rekurze.
Funkce zpravidla volá sama sebe s upravenými parametry a končí až ve chvíli, kdy je splněna ukončující podmínka.

import turtle

def vlocka(t, delka):
    if delka < 3:
        return
    t.forward(delka / 3)
    t.left(60)
    vlocka(t, delka / 3)
    t.right(120)
    vlocka(t, delka / 3)
    t.left(60)
    t.forward(delka / 3)

t = turtle.Turtle()

delka = 3 * 3 * 3 * 3 * 3 * 3
t.penup()
t.back(delka / 2)
t.pendown()
vlocka(t, delka)
 
Odpovědět
30.12.2015 11:43
Avatar
Odpovídá na coells
Milan Šmídl:30.12.2015 12:05

Díky ti člověče, díky moc..měj se kráásně:)

 
Odpovědět
30.12.2015 12:05
Avatar
Ivan Bilík
Člen
Avatar
Ivan Bilík:4.12.2018 17:42

Dobrýden,dočetl jsem se až do deváté lekce.Udělal jsem si představu o složitosti programování.Mám vnuky a rád bych je získal pro studium elektroniky.Začali jsme Arduinem a trápíme se programem ,který by na Oled displeji vykreslil datum a reálný čas.Našel by se někdo, kdo by nám poslal takový kod? Děkuju Bilík I. email bilik.ivan@seznam.cz

 
Odpovědět
4.12.2018 17:42
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Jan Koloničný:9.4.2019 15:18

Ahoj,
U těch N-rozměrných polí ať koukám, jak koukám se mi neshoduje obrázek s tím zápisem v programu. Myslím to tak, že strana x má 4 prvky, y taky a z 3 prvky. Takže by to mělo být takhle?

kinosaly = []

for i in range(3):
    kinosal = []
    for j in range(4):
        temp = []
        for k in range(4):
            temp.append(0)
        kinosal.append(temp)
    kinosaly.append(kinosal)

A dále jsem se chtěl zeptat, proč ty zubatá pole jsou přehozená (řádky se sloupcema). Je to kvůli tomu, že sloupce vždy začínají číslem a je to jednodušší pro zápis? Popřípadě jak by zápis vypadal, kdyby například tabulka nezačínala 15kou a bylo by tam místo ní prázdno? Pouze by místo 15 bylo " "?
To znamená, mohlo by to vypadat takhle, kdybych to dělal přesně podle obrázku a nezaměňoval sloupce za řádky?

zubate = [[15, 3, 9, " ", 5], [2, 3, 1, " ", " "], [8, 7, 16, " ", " "], [5, " ", 3, " ", " "], [3, " ", " ", " ", " "]]
for seznam in zubate:
    for prvek in seznam:
        print(prvek, end=" ")
    print(end="\n")
 
Odpovědět
9.4.2019 15:18
Avatar
Michal Novák:29.10.2019 18:17

Tak tady jsem se nějak ztratil...i přes to, že cykly umím třeba v Matlabu, tak tady to fakt nechápu...ta syntaxe mi nejde do hlavy.

Mohl by mi prosím někdo podrobně jak pro blbce vysvětlit tuto syntaxi?

kinosal[2][2] = 1
# 4. řádek
for i in range(1, 4):
kinosal[3][i] = 1
# Poslední řádek
for j in range(0, 5):
kinosal[4][j] = 1

A co znamená (resp. co to dělá)?
temp.append(0)
kinosal.appen­d(temp)
kinosaly.appen­d(kinosal)

 
Odpovědět
29.10.2019 18:17
Avatar
Marián Mídelka:1. ledna 20:30

No ja som to pochopil takto: kinosal [2][2] je stredný riadok, stredný stĺpec(počítaš riadok aj stĺpec 0,1,2) - doplň 1, kinosál 3 (0,1,2,3) riadok je potom 4 predposlený a namiesto i doplní 1 pre 2až4 stĺpec, kinosál 4 je posledný riadok a namiesto j doplníš 1 od 0 po 4 stĺpec - to je 1 až 5 stĺpec. Pokiaľ ide o temp je to vlastne zoznam, kde doplní 0. Zoznam temp je potom doplnený do zoznamu kinosál a ten je zase doplnený do zoznamu kinosály, čiže všade sa vlastne doplnia nuly. Ja som to pochopil tak a sedí mi to.

 
Odpovědět
1. ledna 20:30
Avatar
Pavel Dostal
Člen
Avatar
Pavel Dostal:26. ledna 18:34

Ahoj. Můžete mi někdo poradit, jak dostanu indexy min a maxima? Je možné vyhledávání maxima a minima nějak zjednodušit?

from random import randrange
kinosal = []
for i in range(5):
    temp = []
    for j in range(5):
        cislo=randrange(1,100)
        temp.append(cislo)
    kinosal.append(temp)
mn=mx=temp[0]
for seznam in kinosal:
    for prvek in seznam:
        print(prvek, end="\t")
    print(end="\n")
x=y=index_x=index_mn=0
for seznam in kinosal:
    x+=1
    for prvek in seznam:
        y+=1
        if mx<prvek:
            mx=prvek
            index_maxy=y
            index_maxx=x
        elif mn>prvek:
            mn=prvek
            index_mn=y
            index_mnx=x
print(f'Minimum 2D pole je {mn}, maximum je {mx}.')
print(f'Index minima je x={index_mnx}, y={index_mn}. Index maxima je x={index_maxx}, y={index_maxy}.')
 
Odpovědět
26. ledna 18:34
Avatar
Richard Hlubuček:10. května 15:52

Super lekce! Jasný a jednoduchý příklad, který dá hodně. Díky gcx11 :)

Odpovědět
10. května 15:52
I have no name, I am but two days old.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 20. Zobrazit vše