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.

David Moravec, MVP
Mainstream Technologies