I needed to join dictionaries from within a list together, so that they become one whole dictionary.
First I thought it may be a trivial task. Than I used google and realized, that everything on the first page was just wrong or impracticable for lists with unknown size.
What I found, was stuff like:
$a = @{"foo"=1} $b = @{"bar"=2} $c = @($a,$b) | ForEach-Object {$_}
and
$a = @{"foo"=1} $b = @{"bar"=2} $c = $a + $b
The console output of $c will look identical for both:
Name Value ---- ----- foo 1 bar 2
But the issue is with the data structure. This becomes a problem when we would like to access the data.
E.g.
$c['foo']
Will output $null for the first example and “2” for the 2nd. But why is this?
Lets convert it to json (without piping, this is important) to see:
ConvertTo-Json -InputObject $c
which outputs for the first case:
[ { "foo": 1 }, { "bar": 2 } ]
and for the 2nd what we originally expected:
{ "bar": 2, "foo": 1 }
So now we know that the first one did not join the dictionaries, but warped them into a list. As we originally looked for a solution to join a list of dictionaries, this is not helpful.
(From now on $c is the output from the first example, as it is the same as my original input)
The 2nd one however looks helpful, but has two issues:
- It only works if we know how many elements we have (hard coded element count)
- It copies the list once for each element we want to add to it.
So let’s address these issues:
- For the 1st one something like this will do the trick:
$c | ForEach-Object -Begin {[Hashtable]$aa = @{}} -Process {$aa += $_} -End {$aa} | ConvertTo-Json
- But for the 2nd we need something a bit more advanced like
$c | ForEach-Object -Begin {[Hashtable]$aa = @{}} -Process {foreach($element in ($_.GetEnumerator())) {$aa.Add($element.Key,$element.Value)}} -End {$aa} | ConvertTo-Json