Krajta poskytuje výkonné datové struktury zvané seznamy, které mohou ukládat a manipulovat s kolekcemi prvků. Poskytuje také mnoho způsobů, jak vytvořit 2-rozměrné seznamy/pole. Je však třeba znát rozdíly mezi těmito způsoby, protože mohou vytvářet komplikace v kódu, které může být velmi obtížné vysledovat. V tomto článku prozkoumáme správný způsob použití 2D polí/seznamů v Pythonu.
Správným způsobem používat 2D pole/seznamy
Správné používání 2D polí/seznamů vyžaduje pochopení struktury, přístup k prvkům a efektivní manipulaci s daty ve dvourozměrné mřížce. Při práci se strukturovanými daty nebo mřížkami mohou být užitečná 2D pole nebo seznamy. 2D pole je v podstatě seznam seznamů, který představuje strukturu podobnou tabulce s řádky a sloupci.
Vytvoření 1-D seznamu
V Pythonu vyžaduje inicializace kolekce prvků v lineární sekvenci vytvoření 1D pole, což je základní proces. Přestože Python nemá vestavěnou datovou strukturu zvanou ‚1D pole‘, můžeme použít seznam, který může dosáhnout stejné funkčnosti. Seznamy Pythonu jsou dynamické a všestranné, díky čemuž jsou vynikající volbou pro reprezentaci 1D polí. Začněme tím, že se podíváme na běžné způsoby vytvoření 1d pole o velikosti N inicializovaného s 0s.
Vytváření 1D seznamu pomocí naivních metod
Ruční inicializace a naplnění seznamu bez použití jakýchkoli pokročilých funkcí nebo konstrukcí v Pythonu je známá jako vytváření 1D seznamu pomocí naivních metod.
Python3
N>=> 5> ar>=> [>0>]>*>N> print>(ar)> |
>
>
Výstup
[0, 0, 0, 0, 0]>
Vytváření 1D seznamu pomocí funkce List Comprehension
Zde násobíme počet řádků prázdným seznamem, a proto je celý seznam vytvořen s každým prvkem nula.
Python3
N>=> 5> arr>=> [>0> for> i>in> range>(N)]> print>(arr)> |
>
>
Výstup
[0, 0, 0, 0, 0]>
Vytvoření 2D seznamu
Správné používání 2D polí/seznamů vyžaduje pochopení struktury, přístup k prvkům a efektivní manipulaci s daty ve dvourozměrné mřížce. Osvojením si používání 2D polí můžete výrazně zlepšit svou schopnost zpracovávat složitá data a efektivně provádět různé operace.
Vytváření 2D seznamu pomocí Naivní metoda
Zde násobíme počet sloupců a dostáváme tedy 1-D seznam o velikosti rovnající se počtu sloupců a pak jej vynásobíme počtem řádků, což vede k vytvoření 2-D seznamu.
Python3
rows, cols>=> (>5>,>5>)> arr>=> [[>0>]>*>cols]>*>rows> print>(arr)> |
hashtable java
>
>
Výstup
[[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]]>
Poznámka: Použití této metody může někdy způsobit neočekávané chování. V této metodě bude každý řádek odkazovat na stejný sloupec. To znamená, že i když aktualizujeme pouze jeden prvek pole, aktualizuje se stejný sloupec v našem poli.
Krajta
rows, cols>=> (>5>,>5>)> arr>=> [[>0>]>*>cols]>*>rows> print>(arr,>'before'>)> arr[>0>][>0>]>=> 1> # update only one element> print>(arr,>'after'>)> |
>
>
Výstup
([[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]], 'before') ([[1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0]], 'after')>
Vytvoření 1D seznamu pomocí Porozumění seznamu
Zde v podstatě používáme koncept porozumění seznamu a aplikujeme smyčku na seznam uvnitř seznamu, a tím vytváříme 2-D seznam.
Python3
rows, cols>=> (>5>,>5>)> arr>=> [[>0> for> i>in> range>(cols)]>for> j>in> range>(rows)]> print>(arr)> |
>
>
rovná se metoda v Javě
Výstup
[[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]]>
Vytvoření 1D seznamu pomocí Prázdný seznam
Zde připojujeme nuly jako prvky pro určitý počet sloupců a poté přidáváme tento 1-D seznam do prázdného seznamu řádků, a tím vytváříme 2-D seznam.
Python3
arr>=>[]> rows, cols>=>5>,>5> for> i>in> range>(rows):> >col>=> []> >for> j>in> range>(cols):> >col.append(>0>)> >arr.append(col)> print>(arr)> |
>
>
Výstup
[[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]]>
Inicializace 2D pole
Poskytnutý kód demonstruje dva různé přístupy k inicializaci 2D pole Krajta . Za prvé, polearr>se inicializuje pomocí 2D porozumění seznamu, kde je každý řádek vytvořen jako[0, 0, 0, 0, 0]>. Celé pole je vytvořeno jako seznam odkazů na stejný vnitřní seznam, což má za následek aliasing. Jakákoli změna prvku v jednom řádku se projeví ve všech řádcích. Kód pak ukazuje jiný přístup pomocí pochopení vnořeného seznamu k vytvoření 2D polearr>. Tato metoda se vyhýbá aliasingu tím, že pro každý řádek vytvoří nový seznam, což má za následek správné 2D pole.
Python3
# Python 3 program to demonstrate working> # of method 1 and method 2.> rows, cols>=> (>5>,>5>)> # method 2 1st approach> arr>=> [[>0>]>*>cols]>*>rows> # lets change the first element of the> # first row to 1 and print the array> arr[>0>][>0>]>=> 1> for> row>in> arr:> >print>(row)> # method 2 2nd approach> arr>=> [[>0> for> i>in> range>(cols)]>for> j>in> range>(rows)]> # again in this new array lets change> # the first element of the first row> # to 1 and print the array> arr[>0>][>0>]>=> 1> for> row>in> arr:> >print>(row)> |
>
>
Výstup
[1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [0, 0, 0, 0, 0] [0, 0, 0, 0, 0] [0, 0, 0, 0, 0] [0, 0, 0, 0, 0]>
Vysvětlení:
Očekáváme, že pouze první prvek prvního řádku se změní na 1, ale první prvek každého řádku se změní na 1 v metodě 2a. Toto zvláštní fungování je způsobeno tím, že Python používá mělké seznamy, kterým se pokusíme porozumět.
V metodě 1a Python nevytváří 5 celočíselných objektů, ale vytváří pouze jeden celočíselný objekt a všechny indexy pole arr ukazují na stejný objekt int, jak je znázorněno.

Pokud přiřadíme 0. index jinému celému číslu, řekněme 1, pak se vytvoří nový celočíselný objekt s hodnotou 1 a pak 0. index nyní ukazuje na tento nový objekt int, jak je ukázáno níže

Podobně, když vytvoříme 2d pole jako arr = [[0]*cols]*rows, v podstatě rozšiřujeme výše uvedenou analogii.
- Vytvoří se pouze jeden celočíselný objekt.
- Vytvoří se jeden seznam 1d a všechny jeho indexy ukazují na stejný objekt int v bodě 1.
- Nyní arr[0], arr[1], arr[2] …. arr[n-1] všechny ukazují na stejný objekt seznamu výše v bodě 2.
Výše uvedené nastavení lze vizualizovat na obrázku níže.

Nyní změňme první prvek v prvním řádku arr na arr[0][0] = 1
- arr[0] ukazuje na jediný objekt seznamu, který jsme vytvořili výše. (Pamatujte si, že arr[1], arr[2] …arr[n-1] také všechny ukazují na stejný objekt seznamu).
- Přiřazení arr[0][0] vytvoří nový objekt int s hodnotou 1 a arr[0][0] bude nyní ukazovat na tento nový objekt int. (a stejně tak arr[1][0], arr [2][0] … arr[n-1][0])
To je jasně vidět na obrázku níže.

Takže když jsou takto vytvořena 2d pole, změna hodnot na určitém řádku ovlivní všechny řádky, protože v podstatě existuje pouze jeden celočíselný objekt a pouze jeden objekt seznamu, na který odkazují všechny řádky pole.
Jak byste očekávali, vysledování chyb způsobených takovým používáním mělkých seznamů je obtížné. Proto je lepší způsob, jak deklarovat 2D pole
Python3
rows, cols>=> (>5>,>5>)> print>([[>0> for> i>in> range>(cols)]>for> j>in> range>(rows)])> |
>
>
Výstup
[[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]]>
Tato metoda vytvoří 5 samostatných objektů seznamu, na rozdíl od metody 2a. Jedním ze způsobů, jak to zkontrolovat, je použití operátoru „is“, který kontroluje, zda dva operandy odkazují na stejný objekt.
Python3
rows, cols>=> (>5>,>5>)> # method 2 2nd approach> arr>=> [[>0> for> i>in> range>(cols)]>for> j>in> range>(rows)]> # check if arr[0] and arr[1] refer to> # the same object> print>(arr[>0>]>is> arr[>1>])># prints False> # method 2 1st approach> arr>=> [[>0>]>*>cols]>*>rows> # check if arr[0] and arr[1] refer to the same object prints True because there is only one> #list object being created.> print>(arr[>0>]>is> arr[>1>])> |
>
>
Výstup
False True>