Seriál Windows PowerShell: Hash tabulka (část 54.)

V PowerShellu se hash tabulka (nebudu zde používat české názvy hešovací tabulka, případně asociativní pole) používá relativně často. Existuje již od verze 1, ale časem se jednoduchost jejího použití vylepšovala. Vzhledem k tomu, že jsem v minulých dnes narazil nezávisle na její špatné použití, rozhodl jsem se, že vám dnes představím její použití.

Jak hash tabulka vypadá?

Základní použití je následující:

PS C:\> @{
>> Jmeno = 'David'
>> Prijmeni = 'Moravec'
>> }
>>

Name       Value
----       -----
Prijmeni   Moravec
Jmeno      David

Celá struktura je uzavřena mezi znaky @{ a }. Uvnitř se používá dvojice klíče a hodnoty. K určitému klíči, zde např. Jmeno se přiřazuje hodnota, David. Vyhledávání se poté provádí na základě klíče.

Všimněte si jedné vlastnosti hash tabulky. V příkladu je vidět, že jsem zadal jako první klíč Jmeno, ale ve výsledku je pořadí klíčů prohozené. Hash tabulka nezajišťuje pořadí jednotlivých položek. Ve většině případů nám to nevadí, ale v určitých scénářích bychom zachované pořadí uvítali. Jak na to, si ukážeme dále.

Zkusme si hash tabulku přiřadit do proměnné.

PS C:\> $dm = @{
>> Jmeno = 'David'
>> Prijmeni = 'Moravec'
>> Hobby = 'PowerShell'
>> Zamestnani = 'Mainstream Technologies'
>> }
>> 
PS C:\> $dm

Name         Value
----         -----
Jmeno        David
Hobby        PowerShell
Prijmeni     Moravec
Zamestnani   Mainstream Technologies

Vidíte, že použití je stejné jako u jiných datových typů. Hodnotu přiřadíme a dále použijeme. K jednotlivým položkám přistupujeme jako k vlastnostem objektu.

PS C:\> $dm.Jmeno
David
PS C:\> $dm.Zamestnani
Mainstream Technologies

Nebo pomocí „indexu“

PS C:\> $dm['Jmeno']
David
PS C:\> $dm['Zamestnani']
Mainstream Technologies

Do hash tabulky můžeme hodnoty přidávat:

PS C:\> $dm.Add('OblibenyNapoj','Kava')
PS C:\> $dm

Name            Value
----            -----
Jmeno           David
Hobby           PowerShell
Prijmeni        Moravec
Zamestnani      Mainstream Technologies
OblibenyNapoj   Kava

Nebo je mazat:

PS C:\> $dm.Remove('Zamestnani')
PS C:\> $dm

Name            Value
----            -----
Jmeno           David
Hobby           PowerShell
Prijmeni        Moravec
OblibenyNapoj   Kava

Použití

Existují zřejmě dva nejčastější způsoby použití. Při vytváření nových objektů a pro shromažďování informací. Při vytváření nových objektů se používá následujícím způsobem.

PS C:\> New-Object -TypeName PSObject -Property @{Jmeno='david';Prijmeni='moravec'}

Prijmeni  Jmeno
--------  -----
moravec   david

Stejně bychom mohli použít již existující hash tabulku.

PS C:\> New-Object -TypeName PSObject -Property $dm

Jmeno   Hobby        Prijmeni   OblibenyNapoj
-----   -----        --------   -------------
David   PowerShell   Moravec    Kava

Nyní si ukážeme, jak zajistit to, abychom vlastnosti měli v určeném pořadí. Jak jsem již říkal, v některých případech nám nejednoznačnost nevadí, ale zrovna v případě vytváření objektů se nám jasné pořadí vlastností hodí. Ve starších verzích PowerShellu jste museli použít následující trik:

PS C:\> New-Object -TypeName PSObject -Property $dm | Select-Object Jmeno, Prijmeni, Hobby, OblibenyNapoj

Jmeno   Prijmeni   Hobby        OblibenyNapoj
-----   --------   -----        -------------
David   Moravec    PowerShell   Kava

Po vytvoření objektu si zajistíme pořadí vlastností voláním cmdletu Select-Object. Od PowerShellu v3 můžeme použít tzv. setříděnou hash tabulku.

PS C:\> $dm2 = [ordered]@{
>> Jmeno = 'David'
>> Prijmeni = 'Moravec'
>> Hobby = 'PowerShell'
>> Zamestnani = 'Mainstream Technologies'
>> }
>> 
PS C:\> $dm2

Name         Value
----         -----
Jmeno        David
Prijmeni     Moravec
Hobby        PowerShell
Zamestnani   Mainstream Technologies

Všimněte si rozdílu ve výstupu, vše je zapsáno tak, jak jsme chtěli. Nyní si můžeme vyrobit nový objekt.

PS C:\> New-Object -TypeName PSObject -Property $dm2

Jmeno   Prijmeni   Hobby        Zamestnani
-----   --------   -----        ----------
David   Moravec    PowerShell   Mainstream Technologies

Nyní si ukážeme další použití hash tabulky. V určitých případech se nám hodí, že hash tabulka má pouze jediný klíč, ke kterému můžeme přiřazovat hodnoty. Nejčastějším použitím je vytváření různých statistik.

PS C:\> $h=@{}
PS C:\> cd Temp
PS C:\Temp> ls|%{$h[$_.Extension]=$h[$_.Extension]+1}
PS C:\Temp> $h

Name      Value
----      -----
.hta      1
.cmd      3
.PML      1
.png      15
.xsd      1
.html     4
.xml      12
.pssc     1
.clixml   1
.csv      12
.ps1      9

… zkráceno

Dokážete odhadnout, co jsme právě vyrobili? Nejprve jsme provedli výpis obsahu adresáře (poté, co jsme vytvořili prázdnou hash tabulku) a poté jsme do hash tabulky pro každý soubor uložili jeho příponu a ve výsledku spočítali celkový výskyt souborů určitého typu. Nyní můžeme výsledky dále zpracovat.

PS C:\Temp> $h | sort Value

Name    Value
----    -----
.hta    1
.cmd    3
.PML    1
.png    15
.xsd    1
.html   4
.xml    12

…zkráceno

Vidíme, že standardním způsobem se nám třídění nepodařilo. Pro správné setřídění musíme použít metodu GetEnumerator, která nám zajistí přístup k jednotlivým položkám tak, jak očekává cmdlet Sort-Object.

PS C:\Temp> $h.GetEnumerator() | sort Value –Descending

Name    Value
----    -----
        19
.png    15
.csv    12
.xml    12
.ps1    9
.txt    8
.exe    6
.html   4

Nyní vidíme, že třídění proběhlo již podle předpokladů. Pokud by vás zajímalo více informací k hash tabulkám, můžete se podívat do velice pěkně zpracované nápovědy about_Hash_Tables.