question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Enhance `foreach` loops to allow iterating over multiple, parallel collections in tandem (pairs)

See original GitHub issue

Summary 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:closed
  • Created 3 years ago
  • Reactions:5
  • Comments:10 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
rjmholtcommented, May 13, 2021

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.

1reaction
mklement0commented, Apr 12, 2021

@iRon7, implementing an analogous feature for use streaming use, in the pipeline, makes sense to me (as in the $PSIndex, index-variable in foreach 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:

# WISHFUL THINKING
{ 0..2 }, { 'a'..'c' } | ForEach-Object -InvokeScriptBlocks { '{0}: {1}' -f $_[0], $_[1] }
0: a
1: b
2: c
Read more comments on GitHub >

github_iconTop Results From Across the Web

Parallel iteration on multiple collections - java
It means you cannot iterate over more than one collection at same time using for-each . You will have to use separate iterators...
Read more >
Write a simple Parallel.ForEach loop
This article shows how to use a Parallel.ForEach loop to enable data parallelism over any System.Collections.IEnumerable or System.
Read more >
Nesting foreach loops
The outer foreach is iterating over the values in bvec , passing them to the inner foreach , which iterates over the values...
Read more >
How to iterate through a collection of items in a Parallel ...
In PowerShell, you can iterate through objects with a ForEach-Object loop like ... It allows for parallel execution of the script blocks within...
Read more >
foreach() loop vs Stream foreach() vs Parallel ...
The foreach loop is concerned over iterating the collection or array by storing each element of the list on a local variable and...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found