一种通过索引过滤范围的方法,只从过滤的索引中获取min_element?

Pio*_*ycz 6 c++ templates boost c++11 c++14

在对这个问题的评论中,有一个迭代过多的元素 - 使用基于范围的循环还有一个额外的问题 - 这可能有"索引视图"在容器上,即具有过滤掉一些索引的子范围.

另外,我遇​​到了一个问题,即从过滤掉一些索引的范围中找到最小值.

也就是说,可以用std和/或boost算法,过滤器替换下面的代码 - 使其更具可读性和可维护性:

template <typename Range, typename IndexPredicate>
auto findMin(const Range& range, IndexPredicate ipred) 
     -> boost::optional<typename Range::value_type>
{
    bool found = false;
    typename Range::value_type minValue{};
    for (std::size_t i = 0; i < range.size(); ++i)
    {
        if (not ipred(i))
            continue;
        if (not found)
        {
            minValue = range[i];
            found = true;
        }
        else if (minValue > range[i])
        {
            minValue = range[i];
        }
    }
    if (found)
    {
        return minValue;
    }
    else
    {
        return boost::none;
    }
}
Run Code Online (Sandbox Code Playgroud)

就像这样使用:

#include <iostream>
#include <vector>

int main() {
    std::vector<float> ff = {1.2,-1.2,2.3,-2.3};
    auto onlyEvenIndex = [](auto i){ return (i&1) == 0;};

    auto minValue = findMin(ff, onlyEvenIndex);
    std::cout << *minValue << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

Tem*_*Rex 6

使用最近的标准范围-v3提案:

#include <range/v3/all.hpp>
#include <iostream>
#include <vector>

int main() 
{
    std::vector<float> rng = {1.2,-1.2,2.3,-2.3};

    auto even_indices = 
        ranges::view::iota(0ul, rng.size()) | 
        ranges::view::filter([](auto i) { return !(i & 1); })
    ;
    auto min_ind = *ranges::min_element(
        even_indices, [&rng](auto L, auto R) { 
        return rng[L] < rng[R]; 
    });
    std::cout << rng[min_ind];
}
Run Code Online (Sandbox Code Playgroud)

实例.请注意,语法大致类似于Boost.Range,但完全改进以利用C++ 14(广义lambdas,自动返回类型演绎等)