Back to basics: Hashtables
One of the most usefull features in PowerShell are arrays, i already talked about them in a previous post. Today i’ll write about their sister: Hashtables.
Hashtables are really awesome for your daily scripting work, in many scripts they are at the center becauseyou can access item not only with the index, but by whatever label you want. Imagine building your parameters in only one object and pushing it to the cmdlet, its fucking more readable and practical for you. A friend of mine, Carlo, calls it “Splatting“. Also, you can also use hashtables formatting your fields and output them with Format-T*. We’ll see more examples at the end of this post.
It’s kinda easy to use, to let’s start quickly.
How to create a Hashtable ?
Like always in PowerShell you will have many ways to create your hashtable. The first is to use @{}.
# The easiest way $MyHash = @{Test=1,5;"Test 2"="This is not a test"}
PS F:\PowerShell> $MyHash = @{Test=1,5;"Test 2"="This is not a test"} PS F:\PowerShell> $MyHash Name Value ---- ----- Test {1, 5} Test 2 This is not a test
Look the created object and available methods.
PS F:\PowerShell> $MyHash | Get-Member TypeName : System.Collections.Hashtable Name MemberType Definition ---- ---------- ---------- Add Method void Add(System.Object key, System.Object value), void IDictionary.Add(Syste... Clear Method void Clear(), void IDictionary.Clear() Clone Method System.Object Clone(), System.Object ICloneable.Clone() Contains Method bool Contains(System.Object key), bool IDictionary.Contains(System.Object key) ContainsKey Method bool ContainsKey(System.Object key) ContainsValue Method bool ContainsValue(System.Object value) CopyTo Method void CopyTo(array array, int arrayIndex), void ICollection.CopyTo(array arra... Equals Method bool Equals(System.Object obj) GetEnumerator Method System.Collections.IDictionaryEnumerator GetEnumerator(), System.Collections... GetHashCode Method int GetHashCode() GetObjectData Method void GetObjectData(System.Runtime.Serialization.SerializationInfo info, Syst... GetType Method type GetType() OnDeserialization Method void OnDeserialization(System.Object sender), void IDeserializationCallback.... Remove Method void Remove(System.Object key), void IDictionary.Remove(System.Object key) ToString Method string ToString() Item ParameterizedProperty System.Object Item(System.Object key) {get;set;} Count Property int Count {get;} IsFixedSize Property bool IsFixedSize {get;} IsReadOnly Property bool IsReadOnly {get;} IsSynchronized Property bool IsSynchronized {get;} Keys Property System.Collections.ICollection Keys {get;} SyncRoot Property System.Object SyncRoot {get;} Values Property System.Collections.ICollection Values {get;}
We can access methods like theses in arrays (Add, Clone, Remove). But there is more, we’ll take a look later in this article.
If you like the path to complexity (or at least write more code)…
PS F:\PowerShell> $NewHash = New-Object System.Collections.Hashtable PS F:\PowerShell> $NewHash | Get-Member | select typename -Unique TypeName -------- System.Collections.Hashtable
Either you use this or the previous one, unlike arrays, you will have an unique Object type to work with.
Add rows to hashtables
Alright now we have a hashtable, let’s see how adding labels/values.
PS F:\PowerShell> $MyHash["Test 3"] = 42 PS F:\PowerShell> $MyHash Name Value ---- ----- Test 2 This is not a test Test 3 42 Test {1, 5}
This way is good when you have multiple words in your label, another way to add a row, is this one
PS F:\PowerShell> $MyHash.Addsomevalue = 1664 PS F:\PowerShell> $MyHash Name Value ---- ----- Addsomevalue 1664 Test 2 This is not a test Test 3 42 Test {1, 5}
As rows are always composed with a label and the associated value, if we want to use the Add method this is what to do.
PS F:\PowerShell> $MyHash.Add("TestAdd","CantWaitNewStarWars") PS F:\PowerShell> $MyHash Name Value ---- ----- Addsomevalue 1664 Test 2 This is not a test Test 3 42 TestAdd CantWaitNewStarWars Test {1, 5}
Remove rows in hashtables
We’ll use the remove method
PS F:\PowerShell> $MyHash.Remove("Test") PS F:\PowerShell> $MyHash Name Value ---- ----- Addsomevalue 1664 Test 2 This is not a test Test 3 42 TestAdd CantWaitNewStarWars
Kinda easy isn’t it ? 🙂
Sort a hashtable
One thing to know about hashtables is their not ordered by default, it means if you wan a real order you have to use some tips !
The first possibility is to create your hashtable using [ordered] which will garanty the order supplied in the definition of your hashtable.
# Not ordered $HashNotOrdered = @{Test="blah blah";"Test 2"="This is not a test";Test3=1} $HashNotOrdered # Ordered $MyHashOrdered = [ordered]@{Test="blah blah";"Test 2"="This is not a test";Test3=1} $MyHashOrdered
Name Value ---- ----- Test3 1 Test 2 This is not a test Test blah blah Test blah blah Test 2 This is not a test Test3 1
Another method is to access elements, with the GetEnumerator method.
PS F:\PowerShell> $Hash = @{Test="blah blah";"Test 2"="This is not a test";Test3=1} PS F:\PowerShell> $Hash.GetEnumerator() | Get-member TypeName : System.Collections.DictionaryEntry Name MemberType Definition ---- ---------- ---------- Name AliasProperty Name = Key Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() Key Property System.Object Key {get;set;} Value Property System.Object Value {get;set;}
The cool thing with this method as you see, is that you can sort your hashtable by name or by value,
PS F:\PowerShell> # Hash sorted by name PS F:\PowerShell> $Hash = @{Test="blah blah";"Test 2"="This is not a test";Test3=1} PS F:\PowerShell> $Hash.GetEnumerator() | Sort-Object Name
Name Value ---- ----- Test blah blah Test 2 This is not a test Test3 1
And Hash sorted by value
PS F:\PowerShell> # Hash PS F:\PowerShell> $Hash = @{Test="blah blah";"Test 2"="This is not a test";Test3=1} PS F:\PowerShell> $Hash.GetEnumerator() | Sort-Object Value
Name Value ---- ----- Test3 1 Test blah blah Test 2 This is not a test
Playing with hashtables
Cmdlet parameters
You can compose arguments with a hashtable and call the variable with @variablename
PS F:\PowerShell> $params = @{Name="Notepad";whatif=$true} PS F:\PowerShell> Stop-Process @params WhatIf : Opération « Stop-Process » en cours sur la cible « notepad (2856) ». WhatIf : Opération « Stop-Process » en cours sur la cible « notepad (3360) ».
All cmdlets accept splatting, so enjoy yourself. Another example building an object only with a hashtable.
PS F:\PowerShell> [psobject]$object = @{Name="PowerShell"; Arg="Really is awesome"} PS F:\PowerShell> $object Name Value ---- ----- Arg Really is awesome Name PowerShell
All right, this is all for today, hope you find this usefull ! If you have any question, or if i made mistakes or forget something on technical facets of hashtables, please feel free to comment this article.
If you want to go further with hashtables and you do some advanced scripting, take a look at PSBoundParameters to play a little more 🙂