Enhance `foreach` loops to allow iterating over multiple, parallel collections in tandem (pairs)
See original GitHub issueSummary of the new feature/enhancement
Iterating over multiple collections that have corresponding elements iteratively is a common scenario.
This is currently fairly cumbersome, so letting the foreach
statement provide syntactic sugar would be a nice simplification (and would amount to a generalization of the pairwise Linq.Enumerable.Zip()
method):
# 3 collections with corresponding elements('foo' relates to 'baz' and 'and', 'bar' relates to 'qux' and 'so on')
$a = 'foo', 'bar'
$b = 'baz', 'qux'
$c = 'and', 'so on'
# WISHFUL THINKING
# Iterate over the corresponding elements from each RHS collection.
# Note: Number of iterator variables must match the number of collections.
foreach ($aElem, $bElem, $cElem in $a, $b, $c) {
"$aElem, $bElem, $cElem"
}
The above would yield:
foo, baz, and
bar, qux, so on
and would be the equivalent of the (far more cumbersome) following:
foreach ($i in 0..($a.count-1)) {
$aElem, $bElem, $cElem = $a[$i], $b[$i], $c[$i]
"$aElem, $bElem, $cElem"
}
Due to its resemblance to destructuring assignments, I think the purpose of the syntax is easy to infer.
Note:
-
With multiple iterator variables on the LHS (which activates the new feature being introduced), their number would be required to match the number of explicitly listed collections (RHS); e.g.:
-
foreach ($aElem, $bElem, $cElem in $a, $b, $c) { ... }
… VALID: 3 iterator variables, 3 collections -
foreach ($aElem, $bElem in $a, $b, $c) { ... }
… INVALID: only 2 iterator variables vs. 3 collections -
The single-iterator variable (the currently supported syntax) would continue to function as-is; e.g.:
foreach ($elem in $a, $b, $c) { ... }
… RHS is conceived as a single collection to iterate over directly, resulting in 3 iterations with$elem
bound to the values of$a
,$b
,$c
in sequence (irrespective of whether these variables contain scalars or collections).
-
-
The largest among the RHS collections would drive the number of iterations, and the iterator variables would contain
$null
for those collections that have run out of elements.
Backward-compatibility considerations: N/A, because the proposed new syntax currently results in a syntax error.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:5
- Comments:10 (5 by maintainers)
Top GitHub Comments
Sorry, I had the wrong tab open before.
I discussed this with the Engine working group and we don’t think this should be implemented at the language/syntax level. Instead it’s something that LINQ, Python and other languages provide as a method or function. A function for that in PowerShell could be implemented in an external module first before we evaluate whether it should be included in PowerShell itself.
@iRon7, implementing an analogous feature for use streaming use, in the pipeline, makes sense to me (as in the
$PSIndex
, index-variable inforeach
pairing).I do suggest creating a separate issue for that.
As a thought up front: I’m not sure we need new syntax for that, perhaps even a
ForEach-Object
enhancement along the following lines is doable, using script blocks as input that are then executed and stepped through in parallel: