什么是将一元函数应用于向量的某些元素的良好实现?

时间:2015-01-02 07:49:29

标签: c++ algorithm c++11 std

我希望将函数UnaryFunction f应用于std容器的某些元素,给定谓词UnaryPredicate p - 如果将std::partitionstd::for_each结合使用,将会得到什么然后将cppreference.com应用于其中一个分区。

我对C ++很陌生,所以请原谅我的无知。但是,我在<algorithm>中寻找了一个合适的实现,但我似乎无法找到所需的功能。

根据OutputIter的可能实施情况,我提出了以下建议:

template<class InputIt, class UnaryPredicate, class UnaryFunction>
UnaryFunction for_each_if(InputIt first, InputIt last, UnaryPredicate p, UnaryFunction f)
{
    for (; first != last; ++first) {
        if (p(*first))
        {
            f(*first);    
        }        
    }
    return f;
}

返回值按照std::for_each建模,但{{3}}可能是更好的选择。这需要更复杂的实施,所以这次我选择了简洁而精致。替代实施留给读者练习。

我的问题是:在std库中已经有一种既定的方法吗?如果没有,这是否是这种功能模板的合理实现?

2 个答案:

答案 0 :(得分:4)

STL不能很好地支持算法的组合。如您所说,如果您不关心元素的顺序,可以先调用partition,然后在其中一个分区上调用for_each

对于新项目或可以引入库的项目,我强烈建议您查看范围库,例如: Boost.Range或Eric Niebler's range-v3

使用范围库,可以这样做:

template<typename R, typename P, typename F> 
F for_each_if(R& rng, P pred, F f)
{ 
    using namespace boost::adaptors;

    return (rng | filtered(pred) | for_each(f));
}

答案 1 :(得分:1)

就评论而言,似乎没有在std库中实现这一点。然而,正如user2672165指出的那样,谓词可以容易地包括在函数中。为了说明这一点,请参阅for_each example over at cppreference.com的以下修改版本:

#include <vector>
#include <algorithm>
#include <iostream>

struct Sum {
    Sum() { sum = 0; }
    void operator()(int n) { sum += n; }

    int sum;
};

int main()
{
    std::vector<int> nums{3, 4, 2, 9, 15, 267};

    std::cout << "before: ";
    for (auto n : nums) {
        std::cout << n << " ";
    }
    std::cout << '\n';

    std::for_each(nums.begin(), nums.end(), [](int &n){ if (n > 5) n++; });

    // Calls Sum::operator() for each number
    Sum s = std::for_each(nums.begin(), nums.end(), Sum());

    std::cout << "after:  ";
    for (auto n : nums) {
        std::cout << n << " ";
    }
    std::cout << '\n';
    std::cout << "sum: " << s.sum << '\n';
}

这里,谓词被添加到函数中,因此[](int &n){ n++; }现在变为[](int &n){ if (n > 5) n++; },仅将函数应用于大于5的整数元素。

预期输出

before: 3 4 2 9 15 267 
after:  3 4 2 10 16 268 
sum: 303

希望这有助于其他人。