C++の範囲ベースのforループで各値のインデックスを検索します
この投稿では、C++の範囲ベースのforループで各値のインデックスを見つける方法について説明します。
1.ポインタ演算の使用
標準のC++範囲ベースのforループは、各値のインデックスを取得するようには設計されていません。vectorはその要素を連続して格納するため、ポインタ演算を使用してvectorの各要素のインデックスを簡単に決定できます。
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; } |
出力:
Index=0, Value=6
Index=1, Value=3
Index=2, Value=5
Index=3, Value=8
Index=4, Value=7
または、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; } |
出力:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
C++ 20は、範囲ベースのforループでinitステートメントをサポートします。これは通常、初期化子を使用した変数の宣言です。
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; } |
出力:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
2.使用する std::for_each
別の効率的な解決策は、 std::for_each
C++11ラムダを使用します。考え方は同じです。vectorは連続しているため、ポインタ演算を使用して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(), [&v](int &i) { int index = &i - &v[0]; std::cout << "Index: " << index << ", Value=" << i << std::endl; }); return 0; } |
出力:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
または、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; } |
出力:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
C++ 14以降、一般化されたラムダキャプチャを使用して、ラムダオブジェクト自体にローカル変数を定義できます。例えば、
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; } |
出力:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
3.使用する std::accumulate
別のオプションは、 std::accumulate
ヘッダーファイルで定義されている標準アルゴリズム <numeric>
。オプションの4番目のパラメーターでバイナリ関数を渡すことにより、デフォルトの操作をオーバーライドできます。
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; } |
出力:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
4.使用する Boost.Range
プロジェクトにBoostライブラリがある場合は、範囲ベースのforループのvectorで値のインデックスを取得できます。 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; } |
出力:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
5.Range-v3ライブラリの使用
最後に、C++20の基礎を形成するranges-v3ライブラリの列挙されたビューを使用できます。 std::ranges
。これがを使用したエレガントなソリューションです 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; } |
出力:
Index: 0, Value=6
Index: 1, Value=3
Index: 2, Value=5
Index: 3, Value=8
Index: 4, Value=7
これで、C++の範囲ベースのforループで各値のインデックスを見つけることができます。