Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested FOR loops: readability & performance [closed]

I understand nested FOR loops. I understand what they do, and how they do it. But my problem is that they seem horribly unreadable to me.

Take this example:

for (int i = 0, y = 0; y <= ySize; y++) {
    for (int x = 0; x <= xSize; x++, i++) {
        vertices[i] = new Vector3(x, y);
    }
}

Now, this loop is pretty straightforward. It's just an x/y "2 dimensional" loop. But as I add more and more "dimensions" to this nested loop, is there a way to make the code not a horrible mess of nests within nests and stupid amounts of backtracing counter variables (i, x, y, z, etc.)?

Also, does additional nesting affect performance in a linear way, or do additonal FORs make things more and more inefficient as you nest more of them?

like image 728
flatterino Avatar asked Jul 11 '16 10:07

flatterino


People also ask

Is it good to use nested for loops?

Nested loops are useful when for each pass through the outer loop, you need to repeat some action on the data in the outer loop. For example, you read a file line by line and for each line you must count how many times the word “the” is found.

Are nested while loops bad?

No, no problem in nested loops. Although, you may want to encapsulate some of them into methods reflecting what they're doing - that last one becomes skipSpaces() , or some such. Deep nesting can be an indication that you should refactor to split things into different functions.

Are nested for loops faster?

HOWEVER, the conclusion is CONSISTENT: The nested loop is much FASTER. When the iteration time is 100^5, the difference is significant: 321.49 vs 210.05. There is about 1.53-time gap between them.

Are nested for loops slower?

Nested loops are significantly slower; avoid them when a loop has a large number of iterations to perform. Decreasing the amount of work done per iteration and the number of loops increases loop performance. Performance is not the only thing that matters. Code readability and maintainability are key.


2 Answers

I think that the issue you have here is less the nested for loops, and more an unusual use of variables within the loops.

Newlines before the opening braces can help with readability too (although this is subjective).

How about this instead:

int i = 0;

for (int y = 0; y <= ySize; y++)
{
    for (int x = 0; x <= xSize; x++)
    {
        vertices[i++] = new Vector3(x, y);
    }
}

This approach should remain relatively readable for additional dimensions too (in this example I've moved the incrementing of i out to its own line, as suggested by usr).

int i = 0;

for (int y = 0; y <= ySize; y++)
{
    for (int x = 0; x <= xSize; x++)
    {
        for (int a = 0; a <= aSize; a++)
        {
            for (int b = 0; b <= bSize; b++)
            {
                vertices[i] = new Vector3(x, y, a, b);

                i++;
            }
        }
    }
}

Regarding performance, I would suggest focussing on making sure that the code is readable and understandable by a human first, and then measuring the run-time performance, possibly with a tool such as RedGate ANTS

like image 67
Richard Ev Avatar answered Nov 09 '22 14:11

Richard Ev


The usual solution is to refactor into methods which contain one or two for loops, and keep refactoring until each method is clear and not too large.

Another solution to stop the indenting, and to separate the loop-resulting-data from the applying-logic, is to use Linq.

int i = 0;
var coordinates = from y in Enumerable.Range(0, ySize + 1)
                  from x in Enumerable.Range(0, xSize + 1)
                  select new { x, y, i = i++ };

foreach (var coordinate in coordinates) {
    vertices[coordinate.i] = new Vector3(coordinate.x, coordinate.y);
}

This is only if the vertices array is already declared. If you can just create a new array, then you can do simply this:

var vertices = (from y in Enumerable.Range(0, ySize + 1)
                from x in Enumerable.Range(0, xSize + 1)
                select new Vector3(coordinate.x, coordinate.y)
               ).ToArray();
like image 30
Maarten Avatar answered Nov 09 '22 15:11

Maarten