【问题标题】:Is there anything like an execute_if algorithm in stl?stl中是否有类似execute_if算法的东西?
【发布时间】:2020-09-15 10:55:50
【问题描述】:

就像 STL 中有 count_if 和 remove_if 算法一样,我想找到类似 execute_if 的东西,它将条件谓词与函数分开执行。

例如,我想要 1 行使用 2 个 lambda 打印所有赔率,如下所示:

auto vec = vector<int>{ 1,2,3,4,5 };
for_each_if(vec.begin(), vec.end(), [](auto val) {return val % 2 != 0; }, [](auto val) { cout << val; });

用算法来做这件事的好方法是什么?

【问题讨论】:

  • 今天为什么会有这样的算法?仿函数实际上可以做任何事情,并且使用 lambdas 我们可以轻松地组合现有的仿函数。
  • std::for_each 和 lambda 包含一个 if?这比你的提议要清楚得多。
  • execute_if 函数与普通的if 语句有何不同?
  • 关注点分离。例如:一个调用者会发送 ifodds,另一个调用者会发送 ifevens。两者都会发送打印机。或者一个来电者发送了一个数字打印机,另一个人发送了其他东西。两者都会发送 ifodds。
  • 为什么需要两个 lambda?从 C++11 开始,std::copy_if(vec.begin(), vec.end(), std::ostream_iterator(std::cout, " "), [](auto val) {return val %2 != 0;}) 将按照您的要求进行操作(假设您希望输出值之间有空格)。

标签: c++ algorithm stl


【解决方案1】:

如果你有 C++20 支持,你可以使用新的range-library:

std::vector<int> vec{ 1,2,3,4,5 };
for (auto val : vec | std::views::filter([](auto val) { return val % 2 != 0; }))
{
    std::cout << val;
}

或者(当然):

std::vector<int> vec{ 1,2,3,4,5 };
auto filtered = vec | std::views::filter([](auto val) {return val % 2 != 0; });
std::for_each(filtered.begin(), filtered.end(), [](auto val) { std::cout << val; } );

Live Demo

【讨论】:

    【解决方案2】:

    您可以自己编写这样的算法:

    #include <iostream>
    #include <algorithm>
    #include <vector>
    
    
    template <typename IT,typename predicate,typename func>
    void for_each_if(IT begin,IT end,predicate p, func f){
        std::for_each(begin,end,[&f,&p](auto val){
            if (p(val)) f(val);
        });
    }
    
    
    int main() {
        auto vec = std::vector<int>{ 1,2,3,4,5 };
        for_each_if(vec.begin(), vec.end(), [](auto val) {return val % 2 != 0; }, [](auto val) { std::cout << val; });
    }
    

    但是,请准备好进行一场实际上更具可读性的辩论。我绝对更喜欢只将一个函子传递给for_each,而不是将两个函子传递给for_each_if

    关注点分离。一个调用者会发送 ifodds,另一个调用者会发送 ifevens。两者都会发送打印机。

    您不需要额外的算法。上面的替代方案是:

    auto condition = [](auto val) {return val % 2 != 0; };
    auto func = [](auto val) { std::cout << val; };
    auto if_fun = [&condition,&func](auto val){ if (condition(val)) func(val);};
    std::for_each(vec.begin(),vec.end(),if_fun);
    

    您可以根据需要从不同的谓词和不同的函数组合if_fun

    【讨论】:

    • 这是一个方便和清晰的问题。那么按照你的逻辑,我们不需要count_if。我可以自己做一个 foreach 并计算比赛。
    • @GonenI 使用标准算法的原因是可读性和表达性,但这种优势主要源于它们是标准的事实。您可以发明您认为具有超级可读性的最佳算法,但很难与大家都知道的标准算法竞争,文档无处不在,并且经过数百万用户的测试和调试
    • @GonenI 无论如何我并不是要暗示这个“按照你的逻辑,我们不需要 count_if。”如果您在答案中读到此内容,那么也许我解释得不够好
    猜你喜欢
    • 2021-09-29
    • 2016-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    相关资源
    最近更新 更多