The Increment operators in C, C++, Java, JavaScript, and other languages are interesting.
In short, i++
or ++i
is equivalent to using i += 1
or i = i + 1
...but there is a twist. The increment operator, depending on where you put it and more importantly if it is a pre-increment or a post-increment operator can execute before or after something else is done.
Let's start with something basic.
You've probably seen this example on the MDN website.
let x = 3;
const y = x++;
console.log(`x:${x}, y:${y}`);
// Expected output: "x:4, y:3"
let a = 3;
const b = ++a;
console.log(`a:${a}, b:${b}`);
// Expected output: "a:4, b:4"
As a post-increment, x
increases to 4 after it is assigned to y
. As a pre-increment, a
increased to 4 before it is assigned to b
.
Last week, I was writing a sorting algorithm for an assignment and noticed the code I was looking for had quite a bit of increment and decrement operators alone on their own line. So I was wondering how I could use them when calling an array at a specific position.
Let's assume we have an array with four elements. Even though the first index is at 0
, let's have i
and j
assigned to 1
.
let arr = [4, 8, 12, 16];
let i = 1;
let c = arr[i]; // arr[1]
let d = arr[++i]; // arr[2]
let e = arr[i]; // arr[2]
console.log(`c:${c}, d:${d}, e:${e}`);
// Expected output: "c:8, d:12, e:12"
let j = 1;
let f = arr[j]; // arr[1]
let g = arr[j++]; // arr[1]
let h = arr[j]; // arr[2]
console.log(`f:${f}, g:${g}, h:${h}`);
// Expected output: "f:8, g:8, h:12"
We can assume that in the above code that c
and f
are the "before", d
and g
are the "during", and e
and h
are the after.
As a pre-increment, the "during" is the same as the "after". As a post-increment, the "during" is the same as the "before".
What this means is that pre-increments are done before an element is called or used, and that post-increments are done after an element is called or used.
We would see the same behavior with decrement operators only with decreasing values rather than increasing values.
Let's see what happens when we use them in different types of loop structures.
Let's get the for
loops out of the way. The outcome for these structures is quite predictable as the increment step and testing appear to happen after the contents inside the loop have been executed.
for(let a = 0; a < 5; ++a){
console.log(`For Loop A: ${a}`);
}
/*
> "For Loop A: 0"
> "For Loop A: 1"
> "For Loop A: 2"
> "For Loop A: 3"
> "For Loop A: 4"
*/
for(let b = 0; b < 5; b++){
console.log(`For Loop B: ${b}`);
}
/*
> "For Loop B: 0"
> "For Loop B: 1"
> "For Loop B: 2"
> "For Loop B: 3"
> "For Loop B: 4"
*/
Pretty boring, amirite? This is why in a lot of computer science books, there's more of an emphasis on while
and do-while
because a while
loop tests before it executes an iteration (step) and a do-while
loop tests after it executes an iteration.
In the table below, we will demonstrate sixteen examples. The first and second columns will show an example of the while loop. The third and fourth columns will show examples of a do-while loop. The first and third columns are the source code and the second and fourth columns are the output.
Rows A through D will show examples using pre-increments while rows E through H will show examples using post-increments. In Rows A and E, the increment will be done in the test (which may be before or after the code block); In rows B and F, the increment will be before the output statement; In Rows C and G, during the output; In Rows D and H, after the output statement. Let's see what patterns we can learn from these tests.
Row | Code | Output | Code | Output |
---|---|---|---|---|
A |
let a = 0; while(++a < 5){ console.log(`While Loop A: ${a}`); } |
> "While Loop A: 1" > "While Loop A: 2" > "While Loop A: 3" > "While Loop A: 4" |
let a = 0; do{ console.log(`Do-While Loop A: ${a}`); }while(++a < 5); |
> "Do-While Loop A: 0" > "Do-While Loop A: 1" > "Do-While Loop A: 2" > "Do-While Loop A: 3" > "Do-While Loop A: 4" |
B |
let b = 0; while(b < 5){ ++b; console.log(`While Loop B: ${b}`); } |
> "While Loop B: 1" > "While Loop B: 2" > "While Loop B: 3" > "While Loop B: 4" > "While Loop B: 5" |
let b = 0; do{ ++b; console.log(`Do-While Loop B: ${b}`); }while(b < 5); |
> "Do-While Loop B: 1" > "Do-While Loop B: 2" > "Do-While Loop B: 3" > "Do-While Loop B: 4" > "Do-While Loop B: 5" |
C |
let c = 0; while(c < 5){ console.log(`While Loop C: ${++c}`); } |
> "While Loop C: 1" > "While Loop C: 2" > "While Loop C: 3" > "While Loop C: 4" > "While Loop C: 5" |
let c = 0; do{ console.log(`Do-While Loop C: ${++c}`); }while(c < 5); |
> "Do-While Loop C: 1" > "Do-While Loop C: 2" > "Do-While Loop C: 3" > "Do-While Loop C: 4" > "Do-While Loop C: 5" |
D |
let d = 0; while(d < 5){ console.log(`While Loop D: ${d}`); ++d; } |
> "While Loop D: 0" > "While Loop D: 1" > "While Loop D: 2" > "While Loop D: 3" > "While Loop D: 4" |
let d = 0; do{ console.log(`Do-While Loop D: ${d}`); ++d; }while(d < 5); |
> "Do-While Loop D: 0" > "Do-While Loop D: 1" > "Do-While Loop D: 2" > "Do-While Loop D: 3" > "Do-While Loop D: 4" |
E |
let e = 0; while(e++ < 5){ console.log(`While Loop E: ${e}`); } |
> "While Loop E: 1" > "While Loop E: 2" > "While Loop E: 3" > "While Loop E: 4" > "While Loop E: 5" |
let e = 0; do{ console.log(`Do-While Loop E: ${e}`); }while(e++ < 5); |
> "Do-While Loop E: 0" > "Do-While Loop E: 1" > "Do-While Loop E: 2" > "Do-While Loop E: 3" > "Do-While Loop E: 4" > "Do-While Loop E: 5" |
F |
let f = 0; while(f < 5){ f++ console.log(`While Loop F: ${f}`); } |
> "While Loop F: 1" > "While Loop F: 2" > "While Loop F: 3" > "While Loop F: 4" > "While Loop F: 5" |
let f = 0; do{ f++ console.log(`Do-While Loop F: ${f}`); }while(f < 5); |
> "Do-While Loop F: 1" > "Do-While Loop F: 2" > "Do-While Loop F: 3" > "Do-While Loop F: 4" > "Do-While Loop F: 5" |
G |
let g = 0; while(g < 5){ console.log(`While Loop G: ${g++}`); } |
> "While Loop G: 0" > "While Loop G: 1" > "While Loop G: 2" > "While Loop G: 3" > "While Loop G: 4" |
let g = 0; do{ console.log(`Do-While Loop G: ${g++}`); }while(g < 5); |
> "Do-While Loop G: 0" > "Do-While Loop G: 1" > "Do-While Loop G: 2" > "Do-While Loop G: 3" > "Do-While Loop G: 4" |
H |
let h = 0; while(h < 5){ console.log(`While Loop H: ${h}`); h++; } |
> "While Loop H: 0" > "While Loop H: 1" > "While Loop H: 2" > "While Loop H: 3" > "While Loop H: 4" |
let h = 0; do{ console.log(`Do-While Loop H: ${h}`); h++; }while(h < 5); |
> "Do-While Loop H: 0" > "Do-While Loop H: 1" > "Do-While Loop H: 2" > "Do-While Loop H: 3" > "Do-While Loop H: 4" |
The output of While Loops B, C, E, and F are all the same. While Loops B, C, and F all have the same output as the Do-While Counterparts. The third line in Do-While Loop C is equivalent to combining lines 2 and 3 in Do-While Loop B. Do-While Loop F's output looks like B and C because of the increment happening before the output statement. While Loop C is probably the best implementation of this loop.
The output of While Loops D, G, and H are all the same and their outputs are the same as their Do-while counterparts.
The third line in While Loop G is equivalent to the third and fourth lines in While H.
Let's look at While Loop A. Here, pre-increment happens before testing, so no a = 0
output. By comparison, While Loop E includes e = 5
just like loops B, C, and F. It's probably not the best idea to do an increment in a test before execution.
The output of Do-While Loops A, D, G, and H are all the same. In Do-While Loops A and D, the increment happens after the output. The output of Do-While Loops G and H are equivalent, and we've described how a couple of paragraphs ago.
Do-While Loop A is probably the best version of this loop because pre-increment and testing happen at the end of execution in one combined statement.
The output of Do-While Loops B, C, and F are all the same. Do-While Loop C is probably the best implementation of this loop.
Let's look at Do-While Loop E. Here we have a post-increment which makes this loop run six times (the most times), which could be described as the behavior opposite of While Loop A which runs four times (the least times). Would this output be the same if we used a less-than-or-equal-to operator instead of a less-than operator? We could probably explore that another time.
The purpose of today's post was to find more efficient ways to write code by finding optimal patterns when using a loop.
I'm thinking in the future to make better use of do-while
loops with counters, but with arrays, I would probably use something a lot more like While Loop G or Do-While Loop G.
Top comments (0)