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.