Powershell hashtable with multiple values and one key

Viewed 31265

Im looking for a data structure/cmdlet that will allow me to add multiple values to a single key in Powershell.

My data would ideally look like this:

KEY-------------------------- VALUES

HOSTNAME1-------------DATABASE1,DATABASE2,DATABASE3

HOSTNAME2-------------DATABASE1,DATABASE2

etc...

I thought a hashtable would do the trick, but I'm unable to do the following:

$servObjects = @{}
$servObjects.Add("server1", @())
$servObjects.get_item("server1") += "database1"

This yields an empty array when I try:

$servObjects.get_item("server1")

I have also tried to do the following, hoping that powershell would understand what I want:

$servObjects2 = @{}
$servObjects2.add($servername, $databasename)

This will unfortunately yield a duplicate key exception

Thanks for any and all input

4 Answers

You basically want a hash table with values that are arrays. You don't have to use $hashtable.get_item or .add

$myHashTable = @{} # creates hash table
$myHashTable.Entry1 = @() #adds an array
$myHashTable.Entry1 += "element1"
$myHashTable.Entry1 += "element2"

This results in the following output:

$myHashTable

Name                           Value                                                                                                                                                                                           
----                           -----                                                                                                                                                                                           
Entry1                         {element1, element2}

$myHashTable.Entry1
element1
element2

In your original example, instead of writing

$servObjects.get_item("server1") += "database1"

you had written

$servObjects.server1 += "database1"

it would have worked.

I'm very new to PowerShell, but I prefer to use

$servObjects.Add("key",@())

over

$servObjects.key = @())

because the .Add will throw a duplicate exception if the key is already present in the hashtable, whereas the assignment will replace an existing entry with a new one. For my purposes, I have found that the implicit replacement is (more often than not) an error, either in my logic, or an anomaly in the input data that needs to be handled.

If you have your data in an array you can group the array and convert to a hash table:

$ary = @()
$ary = $ary + [PSCustomObject]@{RowNumber = 1; EmployeeId = 1; Value = 1 }
$ary = $ary + [PSCustomObject]@{RowNumber = 2; EmployeeId = 1; Value = 2 }
$ary = $ary + [PSCustomObject]@{RowNumber = 3; EmployeeId = 2; Value = 3 }
$ary = $ary + [PSCustomObject]@{RowNumber = 4; EmployeeId = 2; Value = 4 }
$ary = $ary + [PSCustomObject]@{RowNumber = 5; EmployeeId = 3; Value = 5 }

$ht = $ary | Group-Object -Property EmployeeId -AsHashTable

$ht is then:

Name Value
---- -----
3    {@{RowNumber=5; EmployeeId=3; Value=5}}
2    {@{RowNumber=3; EmployeeId=2; Value=3}, @{RowNumber=4; EmployeeId=2; Value=4}}
1    {@{RowNumber=1; EmployeeId=1; Value=1}, @{RowNumber=2; EmployeeId=1; Value=2}}

If you know the value at creation time, it would be clearer this way :

[hashtable]$hash = @{
    HOSTNAME1 = @(DATABASE1, DATABASE2, DATABASE3);
    HOSTNAME2 = @(DATABASE1, DATABASE2);
}

Which will get you the following :

Name                           Value
----                           -----
HOSTNAME2                      {DATABASE1, DATABASE2}
HOSTNAME1                      {DATABASE1, DATABASE2, DATABASE3}
Related