Skip to content

/compare/powershell/where-object-vs-where-method

Where-Object vs .Where(): filtering collections in PowerShell

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
PowerShell
compares
Where-Object vs .Where() method

Where-Object is a cmdlet that filters objects as they stream through the pipeline, so it works on output of any size and starts returning results immediately. .Where({ ... }) is a method on collections that are already in memory; it avoids the pipeline overhead, is usually much faster on large arrays, and has extra modes (First, Last, SkipUntil, Until, Split). Use Where-Object in pipelines, .Where() on variables you already hold.

powershell
Get-Process | Where-Object CPU -gt 100
$procs.Where({ $_.CPU -gt 100 })

Same filter, both ways

powershell
$numbers = 1..10
'Where-Object: ' + ((1..10 | Where-Object { $_ % 3 -eq 0 }) -join ',')
'.Where():     ' + ($numbers.Where({ $_ % 3 -eq 0 }) -join ',')
'First 2:      ' + ($numbers.Where({ $_ -gt 4 }, 'First', 2) -join ',')
'Last:         ' + ($numbers.Where({ $_ -lt 4 }, 'Last') -join ',')
'SkipUntil:    ' + ($numbers.Where({ $_ -ge 8 }, 'SkipUntil') -join ',')
$even, $odd = $numbers.Where({ $_ % 2 -eq 0 }, 'Split')
'Split:        even=' + ($even -join ',') + ' odd=' + ($odd -join ',')
'--- result types when nothing matches:'
'Where-Object returns $null: ' + ($null -eq (1..3 | Where-Object { $_ -gt 9 }))
'.Where() returns an empty ' + $numbers.Where({ $_ -gt 99 }).GetType().Name + ' with Count ' + $numbers.Where({ $_ -gt 99 }).Count

Output

Where-Object: 3,6,9
.Where():     3,6,9
First 2:      5,6
Last:         3
SkipUntil:    8,9,10
Split:        even=2,4,6,8,10 odd=1,3,5,7,9
--- result types when nothing matches:
Where-Object returns $null: True
.Where() returns an empty Collection`1 with Count 0

Criterion by criterion

CriterionWhere-Object.Where()
Inputpipeline (any command output)a collection in a variable or expression
Streamingyes, items flow one at a time; memory stays lowno, the whole collection must exist first
Speed on large arraysslower (pipeline and script block per item)faster
Simplified syntaxWhere-Object Name -like "a*" (no script block)script block only
Modesnone (use Select-Object -First)First, Last, SkipUntil, Until, Split, plus a count
Resultnothing, one object or an arrayalways a Collection (Count 0 when nothing matched)

Measure on your data

powershell
$data = 1..200000
(Measure-Command { $data | Where-Object { $_ % 2 } }).TotalMilliseconds
(Measure-Command { $data.Where({ $_ % 2 }) }).TotalMilliseconds

The difference depends on the machine and the PowerShell version, so measure before rewriting a script for speed. For the fastest filtering of very large arrays, a plain foreach ($x in $data) { if (...) { $x } } loop is another option.

Sources