Can I initialize a PowerShell Hashtable from a loop using a "functional programming" style?

THEOBALD K 60 Reputation points
2025-10-22T18:42:15.2366667+00:00

The usual way to populate a Hashtable using a loop is to create an empty Hashtable and then assign one item per loop iteration. For instance:

$sqrH = @{}

foreach ($i in 1..5) {$sqrH[$i] = $i*$i}

PowerShell lets you create an array in a "functional programming" style by creating the items within the loop but not "consuming" them, and then assigning the "result" of the entire loop to an object. For instance:

$sqrA = foreach ($i in 1..5) {$i*$i}

Is there a way to create a Hashtable using the same paradigm? Something like

$sqrH = foreach ($i in 1..5) { <# ??? #> }

such that $sqrH gets a Hashtable like the first code snippet, but without the "imperative" approach?

Windows for business | Windows Server | User experience | PowerShell
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Marcin Policht 63,720 Reputation points MVP Volunteer Moderator
    2025-10-22T20:00:30.72+00:00

    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


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.