Looping over jagged arrays in C # --- using foreach instead of for?

I am working on a project and I find that I loop through the jagged array multiple times using nested for loops. I am wondering if there could be a tidier way to do this using foreach ?

Here is what I mean:

 for (int ii = 0; ii < xDimension; ii++) { for (int jj = 0; jj < yDimension; jj++) { OutputArray[ii][jj] = someFunction(InputArray[ii][jj]); } } 

Note that I use Jagged arrays, although my data is fixed in size, because notched arrays are faster than multidimensional arrays. Unfortunately, speed is a problem with this project, so, unfortunately, performance outweighs my own OCD encoding requirements.

Is there a way to do this with foreach , which avoids nested for loops, but puts the output in the right place in the OutputArray ? Should there be any gains / losses from this (if possible), except for a bit more tidy code?

+4
source share
5 answers

The following code is neat:

 OutputArray = InputArray.Select(x => x.Select(y => someFunction(y)).ToArray()) .ToArray(); 

But I would just go with loops, because this version of LINQ has a significant drawback: it creates new arrays instead of using existing ones in OutputArray . This argument is controversial if you create an OutputArray right before the loop you showed us.
In addition, reading it is much more difficult.

+2
source

If you really want to create an uneven array as the result, you can use Array.ConvertAll twice:

 var result = Array.ConvertAll(input, array => Array.ConvertAll(array, SomeFunction)); 

This is slightly more efficient than using Select / ToArray from LINQ, because it knows that it will convert the array to another array, so it can instantly create target arrays. Using Select , followed by ToArray , requires the gradual creation of the results, as if you put them in a List<T> , copying them when the buffer is exhausted, and then "right-aligning" the array at the end.

On the other hand, using LINQ (according to Daniel's answer) is likely to be more idiomatic these days ... and the performance difference will usually be negligible. I thought I would give it as another option :)

(Note that this creates new arrays, ignoring the existing OutputArray ... I assume that you can get rid of creating an existing OutputArray , although it may not be ...)

+3
source

With foreach you can get data from an array with an uneven array faster, but since you will not have variables indicating the indices, you cannot effectively set the value of the array, as you do in your example.

If you only wanted to read the values, you can do this:

 foreach(int n in OutputArray.SelectMany(array=>array)) { Console.WriteLine(n); } 

Sequence alignment requires SelectMany , so instead of a sequence of sequences, this is just one sequence.

+1
source

You can even get indexes using LINQ:

 foreach (var t in InputArray.SelectMany( (inner, ii) => inner.Select((val, jj) => new { val, ii, jj }))) { OutputArray[t.ii][t.jj] = someFunction(t.val); } 

but to be honest, the twin- for loop design is much more convenient to maintain.

0
source

Another alternative, just for fun:

 foreach (var item in InputArray.SelectMany(x => x).Select((value, index) => new {value, index})) { var x = item.index / yDimension; var y = item.index % yDimension; OutputArray[x][y] = someFunction(item.value); } 

I would just stick with nested loops.

0
source

All Articles