When you write:
$sqrA = foreach ($i in 1..5) { $i * $i }
PowerShell collects all values output by the loop body and wraps them into an array automatically. The problem is that hashtables aren't collected that way because the foreach loop doesn't have any syntactic way to “accumulate” key/value pairs into a hashtable expression — only objects written to the output stream are accumulated, and those are treated as items, not as dictionary entries. So you can't do something like:
$sqrH = foreach ($i in 1..5) { @{$i = $i*$i} }
and expect PowerShell to merge the dictionaries — it will just produce an array of hashtables, not one merged hashtable.
You can try the following options instead:
Option 1: Use a pipeline with ForEach-Object and [ordered]@{} accumulation
$sqrH = [ordered]@{}
1..5 | ForEach-Object { $sqrH[$_] = $_ * $_ }
This is still somewhat imperative — but readable and compact.
Option 2: Use [System.Linq.Enumerable]
If you want a pure expression without mutation, you can use .NET LINQ to create a hashtable-like object functionally:
$sqrH = [System.Linq.Enumerable]::ToDictionary(
[System.Linq.Enumerable]::Range(1,5),
[Func[int,int]]{ param($x) $x },
[Func[int,int]]{ param($x) $x * $x }
)
That returns a Dictionary[int,int], which behaves much like a PowerShell hashtable:
$sqrH[3] # 9
If you need an actual PowerShell Hashtable, you can wrap it:
$sqrH = @{}
[System.Linq.Enumerable]::Range(1,5) | ForEach-Object { $sqrH[$_] = $_ * $_ }
Option 3: A PowerShell expression-based approach
You can “reduce” (fold) an array into a hashtable using the ForEach-Object -Begin/-Process/-End pattern:
$sqrH = 1..5 | ForEach-Object -Begin {$h=@{}} -Process { $h[$_]=$_*$_ } -End {$h}
AFAIK, this is as close as it gets to a true functional style — there's no external mutation, and $sqrH is the result of a pipeline expression.
If the above response helps answer your question, remember to "Accept Answer" so that others in the community facing similar issues can easily find the solution. Your contribution is highly appreciated.
hth
Marcin