/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.
Get-Process | Where-Object CPU -gt 100
$procs.Where({ $_.CPU -gt 100 })Same filter, both ways
$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 }).CountOutput
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
| Criterion | Where-Object | .Where() |
|---|---|---|
| Input | pipeline (any command output) | a collection in a variable or expression |
| Streaming | yes, items flow one at a time; memory stays low | no, the whole collection must exist first |
| Speed on large arrays | slower (pipeline and script block per item) | faster |
| Simplified syntax | Where-Object Name -like "a*" (no script block) | script block only |
| Modes | none (use Select-Object -First) | First, Last, SkipUntil, Until, Split, plus a count |
| Result | nothing, one object or an array | always a Collection (Count 0 when nothing matched) |
Measure on your data
$data = 1..200000
(Measure-Command { $data | Where-Object { $_ % 2 } }).TotalMilliseconds
(Measure-Command { $data.Where({ $_ % 2 }) }).TotalMillisecondsThe 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
Related pages
commands · powershellSelect-String: the PowerShell equivalent of grepSelect-String -Path *.log -Pattern error prints matching lines with file and line number. It ignores case by default; see -CaseSensitive, -NotMatch, -Context.errors · powershellPowerShell: Cannot index into a null array.You indexed a variable that is $null: a command returned nothing, the name is misspelled or a property is missing. Check the value first or wrap it in @().cheat sheets · powershellPowerShell cheat sheet: files, objects, filtering, strings and error handlingPowerShell cheat sheet: find commands and help, work with files, filter and sort objects, format strings, hashtables, loops, errors and bash equivalents.