-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Description
Summary of the new feature/enhancement
Update for clarification: The gist of this proposal is to bring valuable filter functionality that currently only exists in the in-memory .Where()
array method to its pipeline counterpart, Where-Object
.
(Always using .Where()
isn't an option with large input sets, because you'd have to collect all input in memory first.)
The .Where()
array method, which is the in-memory equivalent of the pipeline-based Where-Object
cmdlet, offers a number of additional features, such as the ability to optionally stop matching after the first match is found, which can be an important optimization technique, and the ability to output all objects that come before/after a matching one:
First
/ -First
example:
# OK - very fast, because - despite the large input collection - processing stops after the first match.
(1..1e6).Where({ $_ -eq 10 }, 'First') # -> 10
# WISHFUL THINKING: Add a -First switch (among several others - see below).
1..1e6 | Where-Object { $_ -eq 10 } -First
# Without it, ALL elements are processed - SLOW
1..1e6 | Where-Object { $_ -eq 10 }
# Current workaround is cumbersome.
1..1e6 | Where-Object { $_ -eq 10 } | Select-Object -First 1
SkipUntil
/ -SkipUntil
example:
(1, 2, 42, 43).Where({ $_ -eq 42 }, 'SkipUntil') # -> 42, 43
# WISHFUL THINKING: Add a -SkipUntil switch.
1, 2, 42, 43 | Where-Object { $_ -eq 42 } -SkipUntil
Based on the current .Where()
features, the following switches should be introduced with the same behavior, mirroring the WhereOperatorSelectionMode
enumeration values:
-First
, -Last
, -SkipUntil
, -Until
, -Split
Note:
-
-Split
partitions the input into two and returns two collections, so it would in effect require collecting all input in memory first before producing output, which would have to be clearly documented. -
The
.Where()
method has an optional numeric parameter,numberToReturn
, that modifies the operations, such as2
withFirst
returning the first two matches; since we don't have a syntax for switches with optional (non-Boolean) arguments for commands (see Feature Request: Variable Parameter with switch-like capability #12104), we have the following options:-
Option A: Simply omit this aspect of the functionality and invariably default to
1
, which is likely fine in the majority of cases; if a different number is needed,Select-Object -First/-Last $n
can be piped to. -
Option B: Implement
-First
and-Last not as _switches, but as
-Firstand
-Last ` ; the potential downside is that a number argument is then mandatory. -
Option C: Given that
numberToReturn
also modifies all other functionality - though there's likely less of a need for that - implement a separate-Count <int>
parameter, which in the absence of any of the switches would imply-First
.
-
-
For these behaviors to be implemented efficiently, they have to stop the pipeline on demand, as
Select-Object
already does. However, the latter does so in a problematic fashion - not giving other cmdlets a chance to run theirEnd
blocks - which should be addressed (independently) as well: see Select-Object -First X skips End{ } blocks of previous cmdlets #7930
On a meta note: You can skip the obsolete comments that follow and resume reading at this comment.