如何在 STL 函数中找到传递给谓词的元素的索引?
How do I find the index of the element being passed to the predicate in STL functions?
考虑以下代码:
std::vector<int> vec(n);
for (auto& elem : vec) {
std::cin >> elem;
}
auto count = 0;
while (!isGood(vec)) {
auto odd_it = std::find_if(vec.begin(), vec.end(), [] (int num) { return ~(num % 2); });
auto even_it = std::find_if(vec.begin(), vec.end(), [] (int num) { return num % 2; });
if(odd_it != vec.end() && even_it != vec.end()) {
std::swap(vec.at(std::distance(vec.begin(), odd_it)), vec.at(std::distance(vec.begin(), even_it)));
count++;
}
else {
count = -1;
break;
}
}
(我知道这不是全部代码,但足以重现问题)
在此代码中,行 auto odd_it
(以及 auto even_it
)将 return 作为向量中的第一个奇数元素。但是,我想要 std::find_if
到 return 一个指向第一个奇数元素的迭代器,它也有一个偶数索引(在这种情况下,巧合的是也恰好也是第一个奇数元素。)
所以,简而言之,问题基本上是找到函数当前正在“处理”的元素的索引(已传递给谓词)
C++17 及更低版本中最明确的解决方案是简单地编写您自己的 find_if
版本,将索引传递给谓词。实现很简单:
template<class Input_it, class Predicate>
Input_it find_if_with_index(Input_it first, Input_it last, Predicate p) {
for (std::size_t i = 0; first != last; ++i, ++first) {
if (p(i, *first))
return first;
}
return last;
}
或者要获取索引,您可以创建自定义迭代器以仅在奇数索引上进行迭代。
与 range-v3,你可以这样做:
auto odd_index_even_value = vec | ranges::view::stride(2)
| ranges::view::filter([](int e){ return e % 2 == 0; });
auto even_index_odd_value = vec | ranges::view::drop(1) | ranges::view::stride(2)
| ranges::view::filter([](int e){ return e % 2 == 1; });
auto it1 = begin(odd_index_even_value);
auto it2 = begin(even_index_odd_value);
int count = 0;
while (it1 != end(odd_index_even_value) && it2 != end(even_index_odd_value)) {
std::swap(*it1, *it2);
++it1;
++it2;
++count;
}
if (it1 != end(odd_index_even_value) || it2 != end(even_index_odd_value)) {
count = -1;
}
考虑以下代码:
std::vector<int> vec(n);
for (auto& elem : vec) {
std::cin >> elem;
}
auto count = 0;
while (!isGood(vec)) {
auto odd_it = std::find_if(vec.begin(), vec.end(), [] (int num) { return ~(num % 2); });
auto even_it = std::find_if(vec.begin(), vec.end(), [] (int num) { return num % 2; });
if(odd_it != vec.end() && even_it != vec.end()) {
std::swap(vec.at(std::distance(vec.begin(), odd_it)), vec.at(std::distance(vec.begin(), even_it)));
count++;
}
else {
count = -1;
break;
}
}
(我知道这不是全部代码,但足以重现问题)
在此代码中,行 auto odd_it
(以及 auto even_it
)将 return 作为向量中的第一个奇数元素。但是,我想要 std::find_if
到 return 一个指向第一个奇数元素的迭代器,它也有一个偶数索引(在这种情况下,巧合的是也恰好也是第一个奇数元素。)
所以,简而言之,问题基本上是找到函数当前正在“处理”的元素的索引(已传递给谓词)
C++17 及更低版本中最明确的解决方案是简单地编写您自己的 find_if
版本,将索引传递给谓词。实现很简单:
template<class Input_it, class Predicate>
Input_it find_if_with_index(Input_it first, Input_it last, Predicate p) {
for (std::size_t i = 0; first != last; ++i, ++first) {
if (p(i, *first))
return first;
}
return last;
}
或者要获取索引,您可以创建自定义迭代器以仅在奇数索引上进行迭代。
与 range-v3,你可以这样做:
auto odd_index_even_value = vec | ranges::view::stride(2)
| ranges::view::filter([](int e){ return e % 2 == 0; });
auto even_index_odd_value = vec | ranges::view::drop(1) | ranges::view::stride(2)
| ranges::view::filter([](int e){ return e % 2 == 1; });
auto it1 = begin(odd_index_even_value);
auto it2 = begin(even_index_odd_value);
int count = 0;
while (it1 != end(odd_index_even_value) && it2 != end(even_index_odd_value)) {
std::swap(*it1, *it2);
++it1;
++it2;
++count;
}
if (it1 != end(odd_index_even_value) || it2 != end(even_index_odd_value)) {
count = -1;
}