Hash Tables (also known as Associative arrays or Dictionaries) are a type of array that allows the storage of paired Keys and Values, rather like a simple database table.
Unlike normal arrays where you refer to each element via a numeric index, the keys of a hash table can be strings. The Key values do still need to be unique, if you try to add the same key twice PowerShell will return an error ("item has already been added").
The built-in properties of a hash table include .Keys .Values and .Count
Create an empty Hash Table, be aware that if a hash table with that name already exists this will re-initialise it, removing any stored values.
$Hash_array_name = @{}
Create a Hash table and immediately populate it with some values:
$array_name = @{key1 = item1; key2 = item2;...}
Note that unlike Arrays which use normal () parenthesis, a Hash table must be created using curly brackets { }
A useful mnemonic to remember this is to think of the H in Hash with it's horizontal bar }H{ and compare with the bracket {H}Example:
$usa_states=@{ CA = "California"; NY = "New York"; "IL" = "Illinois"; "NH" = "New Hampshire" }Notice that placing quotes around the key is optional (unless the key contains spaces).
The semicolons ; between each key/value pair are optional but only if each pair are placed on a separate line.
If you write the hash table definition on one line then the semicolon separators are required.
This is done using the .Add() method, this will not overwrite an existing entry.
$usa_states.Add("GA", "Goregia")You can add new items to either an empty hash table or one thats already been pre-populated with some values.
The key (in this case 'GA') has to be unique.
This is done using the .Set_Item() method:
$usa_states.Set_Item("GA", "Georgia")
This is actually the default action so you can also do:
$usa_states."GA" = "Georgia"If the entry does not already exist it will be automatically added.
This is done by adding the hash variables with the + method, or appending with +=
$world_states = $usa_states + $india_states
This is done using the .Remove() method.
$usa_states.Remove("GA")
To display all contents just use the variable name.
$usa_statesReturn just New York (the quotes are only needed here if the key contains spaces):
$usa_states.'NY'Alternatively to return just New York:
$usa_states['NY']To retrieve two or more key values, pass them as a comma separated array:
$usa_states['NY','IL']If you prefer, you can make the array definition explicit with @( )
$usa_states[@('NY','IL','NH')]
There are 3 main ways to do this:
1) Loop through all keys with ForEach-Object:
$usa_states.keys | ForEach-Object { Write-Output "Key = $_" Write-Output "Value = $($usa_states[$_])" Write-Output '----------' }An alternative way to display the output from the above is to format it with the -f operator:
$message = '{0} key has the value {1}' -f $_, $usa_states[$_]
2) Loop through all keys with ForEach:
ForEach ($state in $usa_states.Keys) { Write-Output "Key = $state" Write-Output "Value = $($usa_states["$state"])" Write-Output '----------' }3) Unwrap the hash table object with GetEnumerator() This passes each key/value pair through the pipeline:
$usa_states.GetEnumerator() | ForEach-Object{ Write-Output "Key = $($_.key)" Write-Output "Value = $($_.value)" }
A hash table is a single PowerShell object, to sort, filter or work with the pipeline you can unwrap this object into it’s individual elements with the GetEnumerator() method.
$usa_states.GetEnumerator() | Sort-Object Name
When unwrapped with GetEnumerator, the hash table returns a collection of (DictionaryEntry) objects, so they must be processed by cmdlets that can accept a collection, or alternatively pass the objects individually via ForEach.
$hashtable.GetEnumerator() | ForEach-Object { … }
or
ForEach($item in $hashtable.GetEnumerator()) {Echo $item … }
ForEach($item in $hashtable.KEYS.GetEnumerator()) {Echo $item … }
A simple test can be made with -eq
If ($usa_states.NY -eq 'New York') {Echo 'OK'}
You can test if a key exists with:
If ($usa_states.NY) {Echo 'OK'}
However be careful, if NY is set to zero or $Null, that test will fail and return $false as if the key didn't exist at all.
There are also the .ContainsKey or .ContainsValue methods, which allow partial matches:
$usa_states.ContainsKey('NY')
$usa_states.ContainsValue('New')
Splatting expands a hash table into a set of command line parameters.
First use @ to create a hashtable containing parameters to a cmdlet:
PS C:\> $stuff = @{path = "c:\demo"; Recurse= $true}Then use @ to SPLAT the parameters:
PS C:\> dir @stuffThat will in effect run: dir -Path c:\demo -Recurse:$true
The paired keys and values become cmdlet parameters and values:PS C:\> $params = @{year = 1980; Month = 5; day = 31}
PS C:\> get-date @paramsThe @ character is also used to create here strings.
An array can be stored as part of a hash table.
This is possible because hash tables use the semi-colon as key-value pair separators, while Arrays use a comma.First create some arrays:
$arrNY = @('Albany', 'Jamestown', ‘New York’, ‘Niagara Falls’) $arrCA = @('Alhambra', 'Berkeley', “Fresno”, “Los Angeles”)Then copy the arrays into the hash table:
$state_towns=@{ NY = $arrNY CA = $arrCA }You can then display the Hash table, one of the arrays or an array element:
PS C:\> $state_towns PS C:\> $state_towns.NY PS C:\> $state_towns.NY[2]This means that the comma-separated output of many cmdlets like Get-Process or Get-ChildItem can be stored directly in a hash table.
Some more examples from Roger Cormier [MSFT] here.
“Nor shall you by your presence make afraid, The kingfisher, who looks down dreamily, At his own shadow gorgeously array'd” - Sir Edmund William Gosse
Related PowerShell Cmdlets:
PowerShell Arrays
get-help about_hash_tables
Variables - Create/read variables.
Everything about hash tables - PowerShell Explained.
PowerShell Hash Table Quirks - The Scripting Guys.