views:

225

answers:

3

Where is the most efficient position for a code block, which shall only execute, if a loop has reached its end, without having previously been aborted (via break or return)?

The question seems banal, the answer obvious, nevertheless I am insecure!

Answer from efficiency/theory professionals very welcome!


  1. Provided: "Some Code X" is always the same, only at different Code Segment Positions 1 and 2.

  2. I assume: 2 will be executed with the same reliability as 1. Am I wrong?

  3. I know: 2 is obviously more efficient, as it is only called once after the loop ran $limit times, compared to 1, whose enclosing if-condition is called $limit times, and if once true, the code itself is called. Thus the efficiency difference is if-condition queried $limit times.

Hence I conclude: To prefer using Code Segment 2 rather than Code Segment 1, unless my assumption is wrong!


for ($i = 0; $i <= $limit; $i++) {
    // Some Code A [...]
    // Executed every iteration.

    // If condition is met, abort the loop and return $result
    if (condition) {
     return $result;
    }

    // Code Segment 1, only executed in last iteration if no abortion happened previously. If-condition checked $limit times!
    if ($i == $limit) {
     // Some Code X [...]
     return $result
    }
}
// Code Segment 2, only executed if no abortion happened. At most executed only once!
// Some Code X [...]
return $result
A: 

if you are using return when you stop a loop, then the second block after the loop will always be executed, as return stops the entire function.

if you are using break. something like the if($i==$limit) statement you have is fine.

GSto
My (@porg) code does not break the loop, but rather returns.@GSto: The return thus exits the entire current code scope (function or file), not only the loop scope!I think you can simply solve the efficiency puzzle entirely logically:If return really exits the entire scope (not only the loop scope) and if the code execution ever reaches Code Segment 2, you can be sure, that the program never returned, thus it must have reached the end of the loop. Much more efficient than I (@porg) initially suggested, and as you, @GSto affirmed, to check if($i==$limit) every iteration.Am I wrong?
porg
A: 

Something like this?:

$aborted = false;
for ($i = 0; $i <= $limit; $i++) {
    // Code
    if ($condition) {
        // Code
        $aborted = true;
        break;
    } else {
        // Code
    }
}

if ($aborted) {
    // Code
} else {
    // Code
}

return $result;

If you're going through an array (or other iterable structure), use a foreach loop and put your "completed loop" code following it.

GZipp
My determination problem is, that I cannot access $i from outside of the for-loop's scope, without using a global variable, as a workaround, as @GZipp suggests.
porg
The scope of a for-loop is the same as the scope that it's within. In my example, all the variables ($aborted, $i, $limit, $condition, $result) are in the same scope.
GZipp
I always assumed that as soon as the for-loop finishes, all its initialized variables from the definition-line: for ($a = 0, $b = 10; $i < $b; $i++) are unset!
porg
@porg: while that is true for some languages (e.g. C and its descendants), it is not for PHP and some other loosely typed and especially script-like languages (e.g. Bash and other shell scripting languages, Python (I think)). As a rule of thumb, if you don't have to explicitly declare your variables, they survive the entire method.
Michael Johnson
You could also drop the $aborted flag in GZipp's example and instead use if ($i <= $limit).
Michael Johnson
Michael - That's true in most cases, but in general it's best to not rely on the value of the loop counter; in any number of scenarios it may not jibe with its expected value or a preset limit.
GZipp
+1  A: 

You have concluded correctly .. segment 2 is far more efficient than segment 1 .. for the reasons you have already stated.

I terms of complexity, in case of the for loop u have O(n) ( where n = $limit ) and incase of segment 2 it is a constant O(1) .. so yes segment 2 is the way to go.

Sabeen Malik