13

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 4

15

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
Sign up to request clarification or add additional context in comments.

1 Comment

I would not use an array for that. Replace "@()" with [System.Collections.Generic.List[string]]::new()" and use $myHashTable.Entry1.Add('element1')
3

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}}

Comments

1

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.

Comments

1

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}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.