Find index of each value in a range-based for-loop in C++
This post will discuss how to find the index of each value in a range-based for-loop in C++.
1. Using pointer arithmetic
The standard C++ range-based for-loops are not designed to get the index of each value. Since a vector stores its elements contiguously, you can easily determine the index of each element of a vector using pointer arithmetic.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> #include <vector> int main() { std::vector<int> v = {6, 3, 5, 8, 7}; for (auto &i: v) { int index = &i - &v[0]; std::cout << "Index=" << index << ", Value=" << i << std::endl; } return 0; } |
Output:
Index=0, Value=6
Index=1, Value=3
Index=2, Value=5
Index=3, Value=8
Index=4, Value=7
Alternatively, we can maintain an explicit counter to keep track of the index for each element of a vector.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <iostream> #include <vector> int main() { std::vector<int> v = {6, 3, 5, 8, 7}; size_t index = 0; for (auto &e: v) { std::cout << "Index: " << index << ", Value=" << e << std::endl; ++index; } return 0; } |
Output:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
C++20 supports an init-statement in the range-based for-loops, which is typically a declaration of a variable with an initializer.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> #include <vector> int main() { std::vector<int> v = {6, 3, 5, 8, 7}; for (size_t index = 0; auto val: v) { std::cout << "Index: " << index << ", Value=" << val << std::endl; ++index; } return 0; } |
Output:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
2. Using std::for_each
Another efficient solution is to use std::for_each with C++11 lambdas. The idea remains the same – get the index of each element of a vector using pointer arithmetic since a vector is contiguous.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> v = {6, 3, 5, 8, 7}; size_t index = 0; std::for_each(v.begin(), v.end(), [&v](int &i) { int index = &i - &v[0]; std::cout << "Index: " << index << ", Value=" << i << std::endl; }); return 0; } |
Output:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
Alternatively, we can maintain an outer variable to hold the index for each element of a vector.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> v = {6, 3, 5, 8, 7}; size_t index = 0; std::for_each(v.begin(), v.end(), [&index] (int &i) { std::cout << "Index: " << index << ", Value=" << i << std::endl; ++index; }); return 0; } |
Output:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
Since C++14, we can use generalized lambda captures to define local variables in the lambda object itself. For example,
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> v = {6, 3, 5, 8, 7}; std::for_each(v.begin(), v.end(), [index = 0] (int &i) mutable { std::cout << "Index: " << index << ", Value=" << i << std::endl; ++index; }); return 0; } |
Output:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
3. Using std::accumulate
Another option is to use the std::accumulate standard algorithm defined in the header file <numeric>. We can override its default operation by passing a binary function in the optional fourth parameter.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <iostream> #include <vector> #include <numeric> int main() { std::vector<int> v = {6, 3, 5, 8, 7}; std::accumulate(v.begin(), v.end(), 0, [](int &index, int &val) -> int { std::cout << "Index: " << index << ", Value=" << val << std::endl; return index + 1; }); return 0; } |
Output:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
4. Using Boost.Range
If you have the boost library in your project, you may get the index of a value in a vector in a range-based for-loop with boost::adaptors::indexed.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <iostream> #include <vector> #include <boost/range/adaptor/indexed.hpp> int main() { std::vector<int> v = {6, 3, 5, 8, 7}; using namespace boost::adaptors; for (auto const &e : v | indexed(0)) { std::cout << "Index: " << e.index() << ", Value=" << e.value() << std::endl; } return 0; } |
Output:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
5. Using Range-v3 library
Finally, we can use the enumerated view of the ranges-v3 library, which forms the basis for C++20’s std::ranges. Here’s an elegant solution using ranges::views::enumerate.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> #include <vector> #include <range/v3/view/enumerate.hpp> int main() { std::vector<int> v = {6, 3, 5, 8, 7}; for (auto const& [index, val] : v | ranges::views::enumerate) { std::cout << "Index: " << index << ", Value=" << val << std::endl; } return 0; } |
Output:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
That’s all about finding the index of each value in a range-based for-loop in C++.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)