如何在 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;   
}

Demo