A PowerShell Hashtable, also known as a dictionary or associative array,
is a compact data structure that stores one or more key/value pairs.
For example, a hash table might contain a series of IP addresses and computer names,
where the IP addresses are the keys and the computer names are the values, or vice versa.
All the keys in the PowerShell Hashtable must be unique – it’s a perfect data structure to store IDs, email addresses or anything else which requires uniqueness.
Adding and retrieving items is blazingly fast with Hashtable, I probably abuse it way too often.
This article is available in the form of a video
Adding items to PowerShell Hashtable
It’s easy to confuse the way to create a new hashtable with an array:
- Hashtable uses curly braces @{}
- The array uses parentheses @()
You can use a method or assign a key directly.
Hashtable can also be cast directly with keys and values.
#Creating a hashtable
$hash = @{}
$hash.Add("Person", "John") #you can use a method to add new key and value
$hash["Email"] = "John@john.com" #or assign key to its value
$hash.Add("Pet", "Cat")
$hash.Add("Surname", "Smith")
# Removing Key from hashtable
$hash.Remove("Surname")
# Prepopulating hashtable
$details = @{
Person = "Mike"
Email = "Mike@Mike.com"
Pet = "Dog"
}
# Adding key that already exists throws an error
$details.Add("Pet", "Snake")
PowerShellAccessing keys
Keys can either be accessed by passing the key, or by accessing its property.
# Accessing with property name
$details['Pet']
$details.Pet
# We can use variable
$property = "Email"
$details[$property]
# Accessing multiple properties
$details["Email", "Person"]
# Non existent value doesn't throw
$details['Surname']
$details.Surname
# Although we can check for true/false
[bool]$details['Surname']
PowerShellUpdating values
Updating values is as easy as providing the key and the new value.
# We can update and add new values
$details['Pet'] = "Snake"
$details['Drink'] = "Flat white"
$details
$details.pet = "Dog"
$details.Food = "Lamb Shish Kebab"
$details
PowerShellLooping over PowerShell Hashtable
There are a few ways to iterate over all the keys.
It’s worth noting for updating the keys during the loop you must use the clone() method.
# using foreach
foreach ($key in $details.Keys) {
"{0} is {1}" -f $key, $details[$key]
}
# piping to foreach-object
$details.Keys | ForEach-Object {
"{0} is {1}" -f $_, $details[$_]
}
# GetEnumerator() allows us to work with properties
$details.GetEnumerator() | ForEach-Object {
"{0} is {1}" -f $_.Key, $_.Value
}
# Values can't be updated while enumarated!
foreach ($key in $details.Keys) {
$details[$key] = 'BLAH'
}
# Keys must be cloned before updating
$details.Keys.Clone() | ForEach-Object {
$details[$_] = "SANITISED"
}
$details
PowerShellTesting hashtable
You often need to check whether key exists before adding it – to avoid overwriting it.
Also, pay attention to how empty string, null and false values are handled in PowerShell Hashtable – you don’t want to be caught by surprise on production!
# checking if hashtable exists
if ($details) {"It's there"}
$empty = @{}
if ($empty) {"It's empty, but it's there!"}
# Checking if key exists
if ($details.Person) {"There's some info about a person"}
if ($details.ContainsKey("Person")) {
"There's some info about a person"
}
# Deailing with false
$details.Add("Empty", "")
$details.Add("Null", $Null)
$details.Add("False", $false)
$details
if ($details.Empty) {"It's there"}
if ($details.Null) {"It's there"}
if ($details.False) {"It's there"}
if ($details.ContainsKey('Null')) {"It's null!"}
PowerShellFunction parameters are PowerShell Hashtable
Since parameters use Hashtable to store its value, you can e.g. validate if an optional parameter has been passed.
function Show-Params {
param(
[string]$Name,
[string]$Email,
[string]$Pet
)
if ($PSBoundParameters.ContainsKey("Name")) {
Write-Host "Hello $Name"
}
return "$Name $Email $Pet"
}
PowerShellCustom expressions
You can use a hashtable to create dynamic properties in flight.
It’s not the prettiest thing to do, but sometimes you just have to do it.
$employee = @{
Name = "Beth"
HourlyWage = 10
HoursWorked = 7.5
}
$employee | Select-Object -Property *,@{N = "Wage"; E = {$_.HourlyWage * $_.HoursWorked } }
PowerShellSplatting – passing arguments elegantly
Splatting is a great technique to pass parameters to the function.
You need to create a hashtable and pass it to the function with @ symbol.
Another great benefit of using splatting is the ability to add new keys to the underlying hashtable.
Rather than having multiple function calls with different parameters, you can have a single call with dynamically added parameters.
Invoke-RestMethod -Uri catfact.ninja/facts -Method Get |
Select-Object Data -ExpandProperty Data
$params = @{
Uri = "catfact.ninja/facts"
Method = "Get"
}
Invoke-RestMethod @params | Select-Object Data -ExpandProperty Data
# Adding parameters
$Verbose = $true
if ($Verbose) {
$params['Verbose'] = $true
}
Invoke-RestMethod @params
PowerShellNested PowerShell Hashtable
You can embed objects within a hashtable, as well as other hashtables.
Such nested construct can then be e.g. used to be sent as a JSON body in the web request.
$Environments = @{
Development = @{
Server = "Server1"
Admin = "Rachel Green"
Credentials = @{
Username = "Serv1"
Password = "Secret"
}
}
Test = @{
Server = "Server2"
Admin = "Joe Triviani"
Credentials = @{
Username = "Serv2"
Password = "Letmein"
}
}
}
# Accessing nested properties
$Environments
$Environments.Keys
$Environments.Values
$Environments.Test
$Environments.Test.Credentials
$Environments['Test']['Credentials']
# Updating nested properties
$Environments.Test.Credentials.Username = "admin"
$Environments.Test.Credentials
# Quickly unwrapping all properties
$Environments | ConvertTo-Json -Depth 99
# Adding nested properties
$Environments['Production'] = @{}
$Environments.Production.Server = "Server3"
$Environments.Production.Admin = "Ross Geller"
$Environments.Production['Credentials'] = @{}
$Environments.Production.Credentials.Username = "Serv3"
$Environments.Production.Credentials.Password = "Nosuchplace"
$Environments | ConvertTo-Json | Out-File C:\temp\envs.json
Get-Content C:\Temp\envs.json | ConvertFrom-Json #This will create pscustomobject
PowerShellPSCustomObject
PsCustomObject can contain hashtables as its properties.
Casting a hashtable to PsCustomObject is super easy as well.
# Creating a new object
$EnvironmentsObject = [pscustomobject]@{
Development = @{
Server = "Server1"
Admin = "Rachel Green"
Credentials = @{
Username = "Serv1"
Password = "Secret"
}
}
Test = @{
Server = "Server2"
Admin = "Joe Triviani"
Credentials = @{
Username = "Serv2"
Password = "Letmein"
}
}
}
# Casting hashtable to object
[PSCustomObject]$Environments
PowerShellWant to learn more about PowerShell?
You can learn how to use Windows PowerShell with my PowerShell course for IT Professionals course.
Or if youโre already familiar with PowerShell, check out the PowerShell Best Practices ebook.
Finally, you can find more code examples on my GitHub.
โ๏ธ Have you found this useful, why not buy me a coffee?