Suppose you’re given an array and you’re only interested in elements at either even or odd indices. How can you construct a loop to handle this situation?
For example, given an array, letters = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’]
Its corresponding indices are [0, 1, 2, 3, 4, 5, 6, 7]
We’re interested in elements at even indices: 0, 2, 4, 6 which corresponds a, c, e, and g respectively.
One way to go about this is to check every index if it’s an even number.
[In this article and many that follow, I’ll be using Go for the examples, but the concepts should apply to any other programming languages.]
letters := []rune{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
for i := 0; i < len(letters); i++ {
if i % 2 == 0 {
fmt.Println("Even index")
}
}
This is an acceptable approach especially if you need to also process other elements.
However, since we’re interested in only even indices, we can do better.
Let’s take a step back and look at how does even numbers look like:-
0, 2, 4, 6, 8, 10, ….
As you can see, except for the first number, the difference between a number and the number before it is always 2.
Based on these observations, we can create a loop that starts at 0 and increases by a step size of 2 at the end of every loop.
fmt.Println("Even indices only")
for i := 0; i < len(letters); i += 2 {
fmt.Printf("Index: %v Value: %v\n", i, string(letters[i]))
}
[Output]
Even indices only
Index: 0 Value: a
Index: 2 Value: c
Index: 4 Value: e
Index: 6 Value: g
Similarly, this is what odd numbers look like:-
1, 3, 5, 7, 9, 11, ….
The difference between two numbers is also 2. However, the starting number is 1 instead of 0.
fmt.Println("Odd indices only")
for i := 1; i < len(letters); i += 2 {
fmt.Printf("Index: %v Value: %v\n", i, string(letters[i]))
}
[Output]
Odd indices only
Index: 1 Value: b
Index: 3 Value: d
Index: 5 Value: f
Index: 7 Value: h
Now what if there’s one more requirement: look for elements at odd indices for indices > x and x is random.
For example, if x = 3, we’ll only process elements at indices 4 and 6.
Again, there are many ways to do this:-
One is to add the condition inside the for loop to ignore all indices lesser than or equal to x:-
x := 3 for i := 0; i < len(slice); i += 2 { if i <= x { continue } fmt.Printf("Index: %v Value: %v\n", i, string(slice[i])) } [Output] Even indices greater than x only Index: 4 Value: e Index: 6 Value: g
This solution is fine because simple task like if i <= x {
generally doesn’t take much computation power and time.
However, this check can be internalized by the for loop.
Here’s the code followed by some explanation.
letters := []rune{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
// x is actually a random number. Using 3 here for demonstration purpose.
x := 3
istart := x
if x % 2 == 0 {
istart += 2
} else {
istart += 1
}
fmt.Println("Odd indices only")
for i := istart; i < len(letters); i += 2 {
fmt.Printf("Index: %v Value: %v\n", i, string(letters[i]))
}
First we check if x is an odd number. In the example above, x is 3 and an odd number, so the starting index for the loop is the next even number which is x + 1 = 4
In a different scenario, if x is 4, the starting index will be 4 + 2 = 6. Recall that the requirement asks to exclude x itself.
What happens if x is 6? Well the starting index will be 6 + 2 = 8 which is out of bound for the array. And since the trigger condition for the for loop is i < len(letters), the for loop will be skipped entirely and there’ll be no errors (which is the correct behavior).
If brevity is your thing you can further reduce the istart calculation code to:-
letters := []rune{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
// x is actually a random number. Using 3 here for demonstration purpose.
x := 3
istart := x + 1
if x % 2 == 0 {
istart += 1
}
fmt.Println("Odd indices only")
for i := istart; i < len(letters); i += 2 {
fmt.Printf("Index: %v Value: %v\n", i, string(letters[i]))
}