特定の条件(たとえば、より大きい)を検証する要素のインデックス位置を見つける方法を知りたいです。たとえば、int値のベクトルがある場合
vector<int> V;
Vには値が含まれています3 2 5 8 2 1 10 4 7
そして、5より大きい要素のすべてのインデックス位置を取得したいのですがstd::find_if
、ドキュメントによると、条件を満たす最初の要素を見つけるだけです。
std::find_if
前回停止したところからループします。
サンプル (動作を確認してください):
std::vector<size_t> results;
auto it = std::find_if(std::begin(v), std::end(v), [](int i){return i > 5;});
while (it != std::end(v)) {
results.emplace_back(std::distance(std::begin(v), it));
it = std::find_if(std::next(it), std::end(v), [](int i){return i > 5;});
}
最初に、最初の結果で反復子を設定します。見つからない場合、while ループは実行されません。それ以外の場合は、インデックス位置が格納され (std::distance
基本的にはより一般的なit - std::begin(v)
)、検索が続行されます。
私は使用すると思いますstd::copy_if
:
std::vector<int> x{3, 2, 5, 8, 2, 1, 10, 4, 7};
std::vector<size_t> y(x.size());
std::iota(y.begin(), y.end(), 0);
std::copy_if(y.begin(), y.end(),
std::ostream_iterator<size_t>(std::cout, " "),
[&](size_t i) { return x[i] > 5; });
私にとって、これは3 6 8
、8、10、および 7 のインデックスを与えますx
- まさに私たちが望むものです。
C++98/03 コンパイラ/ライブラリに行き詰まっている場合は、std::remove_copy_if
代わりに使用します (比較の意味を逆にします)。この場合、比較にラムダを使用することも明らかにできません。
楽しみのために、transform_if
アルゴリズム:
#include <vector>
#include <iterator>
#include <algorithm>
#include <iostream>
template<typename InputIterator, typename OutputIterator,
typename UnaryPredicate, typename UnaryFunction>
OutputIterator
transform_if (InputIterator first, InputIterator last,
OutputIterator result, UnaryPredicate pred,
UnaryFunction func)
{
for (; first != last; ++first, ++result)
if (pred(*first))
*result = func(*first);
return result;
}
int main()
{
std::vector<int> x {3, 2, 5, 8, 2, 1, 10, 4, 7};
std::vector<size_t> indices;
size_t index = 0;
transform_if(x.begin(), x.end(), std::back_inserter(indices),
[&](int i){ return ++index, i > 5; },
[&](int){ return index-1; });
std::copy(indices.begin(), indices.end(),
std::ostream_iterator<size_t>(std::cout, " "));
}
出力:3 6 8
C++20 では、ビューを使用して、次のようにすることができます。
std::ranges::iota_view{0, (int)v.size()}
| std::ranges::views::filter([&v](int i){ return v[i] > 5; })