Search code examples
powershellhashtablekey-value-store

Hashtable vs array of custom objects regarding iteration


I frequently write lists of things and perform enumeration against them to perform some get/set.

I hate enumerating hashtables, since whenever I have to do it, I have to bend my mind backwards to work with hashtable objects.

$hashtablelistofitems = @{}

$hashtablelistofitems.add("i'm a key", "i'm a value")

foreach ($item in $hashtablelistofitems.keys) {
  $item
  $hashtablelistofitems.item($item)
}

Instead, I usually revert to using a single dimensional array of a custom object with two noteproperties.

$array = @()

$listofitems = "" | select key,value

$listofitems.key = "i'm a key"
$listofitems.value = "i'm a value"

$array += $listofitems

foreach ($item in $listofitems) {
  $item.key
  $item.value
}

Why should I be using a hashtable over this method? Simply because it only guarantees a single value per key?


Solution

  • You should use a hashtable if you want to store a key value list and not create an array containing a custom object with two properties (key / values) for mainly two reasons:

    1. You might want to pass your hashtable to a function that expect a hashtable.
    2. Hashtable is a built-in PowerShell type which users are aware of. Your second approach is harder to read / maintain for other users.

    Note: You can iterate over a hashtable almost the same way as your approach by calling the GetEnumerator() function:

    foreach ($item in $listofitems.GetEnumerator()) {
      $item.key
      $item.value
    }
    

    Also, the hashtable comes with handy methods that you might want to use:

    @{} | Get-Member | Where-Object MemberType -eq Method | Select Name
    

    Output:

    Name             
    ----             
    Add              
    Clear            
    Clone            
    Contains         
    ContainsKey      
    ContainsValue    
    CopyTo           
    Equals           
    GetEnumerator    
    GetHashCode      
    GetObjectData    
    GetType          
    OnDeserialization
    Remove           
    ToString