Learn about Windows PowerShell
Summary: Microsoft PFE and guest blogger, Chris Wu, talks about working with hash tables.
Microsoft Scripting Guy, Ed Wilson, is here. Welcome back guest blogger, Chris Wu…
Admittedly, hash tables didn’t catch my attention when I started using Windows PowerShell, but over time it has proven to be one of my favorites. This is largely thanks to its ability to assign names to values for fast lookup.
Hash tables store key-value (or name-value) pairs, which means typically we use strings as keys to locate corresponding values. Windows PowerShell also takes keys from the command line as strings. So the following examples will create the same hash table:
However, it is not a restriction, per se. Any type of data can be used as a key in hash tables. The following example uses int values as keys, which makes a hash table appears like an array, in terms of syntax:
Other than indexing, hash tables also support dot notation to access elements. However, in Windows PowerShell 2.0, dot notation syntax doesn’t support non-string keys. This seems to have been improved in Windows PowerShell 3.0.
Actually, as long as a hash table is manually crafted, there is no mystery. Everything was plain and straightforward to me, until I was hit by this particular issue where I was trying to get a list of fixed logical disks by accessing a hash table that returned from the Group-Object cmdlet with the -AsHashTable parameter:
What? No fixed disks? That’s impossible! So I double checked:
A key called 3 was indeed in the list. The workaround I tried previously also proved that the element was in the hash table. So what the heck?
I scratched my head hard, until finally I realized that those keys are objects too. So each key has its type as well. Then I investigated:
Here we go…
The keys were of the unsigned Int32 type, which are different from the signed Int32 type that Windows PowerShell uses by default. So when Windows PowerShell searched the hash table, looking for an element for Int32 value 3, there was no match! When I figured out that, it became apparent how the elements can be accessed:
One take-away lesson that I learned: Keys in a hash table are unique only when the data and the type are considered. I could create a hash table that contain four keys, all sharing the same look:
Now, how do we get each of those elements?
Thanks, Chris, for another awesome blog post.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
Well, that's tricky. In .NET you'd typically just use System.Collections.Generic.Dictionary object instead of System.Collections.Hashtable, but there's no way to get things like the Group-Object cmdlet to produce that sort of output. This might be a good place for a utility cmdlet or function to convert a hashtable to a Dictionary (producing errors if the hashtable's keys can't be converted to the desired type, or if duplicates are detected.) Then you could do something like this:
$h = Get-WmiObject Win32_LogicalDisk |
Group-Object DriveType -AsHashTable |
ConvertTo-Dictionary -KeyType System.Int32
I wrote a quick function according to the usage I posted earlier. Seems to address the quirks: http://gallery.technet.microsoft.com/scriptcenter/Convert-Hashtable-to-d4f1b765