Algorithms#

PowerShell is rarely the right tool for heavy algorithmic work, but the object pipeline does the equivalent of LINQ in one or two cmdlets. Sort-Object, Group-Object, Compare-Object, Select-Object -Unique, and Measure-Object cover the patterns operators run into most: sort, group, dedupe, diff, aggregate.

Sorting#

Sort-Object covers the standard cases. Sort by property, multi-key sort, descending order, case-insensitive, unique.

$items | Sort-Object
$rows  | Sort-Object Length -Descending
$rows  | Sort-Object Region, Name           # multi-key
$rows  | Sort-Object -Unique Name

For numeric vs lexical sorting, pass an expression with the right type.

'10','2','33','4','5' | Sort-Object               # lexical: 10 2 33 4 5
'10','2','33','4','5' | Sort-Object { [int]$_ }   # numeric: 2 4 5 10 33

Grouping#

Group-Object returns GroupInfo objects with Name (the key), Count, and Group (the underlying rows).

Get-Process |
    Group-Object Company |
    Sort-Object Count -Descending |
    Select-Object Name, Count

# group by computed key
$rows | Group-Object { $_.Email -split '@' | Select-Object -Last 1 }

Dedup#

Three ways, in order of preference for the operator’s everyday work.

$items | Select-Object -Unique                          # in-pipeline
$items | Sort-Object -Unique                            # also sorts
[System.Collections.Generic.HashSet[string]]$items      # .NET, fastest

Diff#

Compare-Object is PowerShell’s structured diff. Returns rows with SideIndicator: <= for reference-only, => for difference-only, == for shared (with -IncludeEqual).

Compare-Object (Get-Content a.txt) (Get-Content b.txt)

Compare-Object $before $after -Property Name |
    Where-Object SideIndicator -eq '=>'

Aggregate#

Measure-Object sums, averages, counts, and finds min / max over a property.

Get-ChildItem -Recurse |
    Measure-Object Length -Sum -Average -Maximum -Minimum

$rows | Measure-Object Count -Sum

Recursion#

function Get-Factorial {
    param([int]$N)
    if ($N -le 1) { return 1 }
    $N * (Get-Factorial -N ($N - 1))
}

Get-Factorial -N 5
120

PowerShell has no tail-call optimization. Deep recursion blows the stack; prefer iteration for anything above a few hundred frames.

References#

  • Structures for the arrays, hashtables, and PSCustomObject these algorithms operate on.

  • I/O and Pipelines for the parallel pipeline (ForEach-Object -Parallel) when the work is independent.

  • Get-Help Sort-Object, Get-Help Group-Object, Get-Help Compare-Object, Get-Help Measure-Object.