Where-Object Vs .Where()

As of powershell 4 there is an alternative way of filtering collections using Where() method. This has some more advanced options that can be quite useful. This method will only be available on collections.

#Comparison of the two types

Get-Service | Where-Object {$_.Status -eq 'Running'}

(Get-Service).Where({$_.Status -eq 'Running'})

The Where() method has some extra arguments it can take that make it able to do more dynamic filtering. You call the method as below:

Where({ expression } [, mode [, numberToReturn]])

The modes available are:

  • Default –¬†Returns all objects that resolved $true
  • First – Returns only the first object that resolved $true
  • Last – Returns only the last object that resolved $true
  • Until – Will return all objects until the first that resolve $true
  • SkipUntil – Will not return any objects until one resolve $true
  • Split – Out puts filtered groups one after the other

Which allow us to do things such as:

#Filter a group and split results into separate variables for later use
PS C:\> $Up,$Down = (Get-NetAdapter).Where({$_.Status -eq 'Up'}, 'Split')

#Filter and return all objects that have a status of okay until you hit the first error.
#This might be helpful for tracing up to what point something has succeeded.
PS C:\> ('ok','ok','ok','error','ok').Where({$_ -eq 'error'}, 'Until')

#The reverse of until could potentiall be used to show you events took place after an error had occurred.
PS C:\> ('ok','ok','ok','error','ok').Where({$_ -eq 'error'}, 'SkipUntil')

It is worth noting also what the Where() method is significantly faster than the traditional Where-Object

#Find all numbers that are divisible by 3 in 1 to 1000000
Measure-Command { 1..1000000 | Where-Object {$_ % 3 -eq 0}} | Select TotalSeconds

Measure-Command {(1..1000000).Where({$_ % 3 -eq 0})} | Select TotalSeconds