清理for循环以匹配元素

时间:2017-12-21 17:34:23

标签: c++ algorithm design-patterns

我发现我编写的很多代码都遵循"循环遍历此容器的模式,并对符合某些条件的元素执行X"。

通常看起来像这样:

std::vector<int> theList(10);
std::iota(theList.begin(), theList.end(), 0);

for (auto i : theList)
{
    if ((i % 2) == 0)
    {
        //Do something with i
    }
}

在这些情况下,我不喜欢if语句 - 它们很丑陋并且会减损循环逻辑中真正发生的事情。

我喜欢的是一种更好的方法,因此很好地表达了问题的核心。

到目前为止,我最好的尝试并不是那么好:

std::vector<int> theList(10);
std::iota(theList.begin(), theList.end(), 0);

auto criteria = [](const int& i) -> bool { return (i % 2) == 0; };

for (auto it = std::find_if(theList.begin(), theList.end(), criteria);
     it != theList.end();
     it = std::find_if(++it, theList.end(), criteria)
     )
{
    std::cout << *it << ", ";
}

感觉这种模式应该以更清洁的方式进入std::algorithm

有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

您可以为此创建一个简单的高阶函数:

template <typename Range, typename Predicate, typename F>
void for_items_matching(Range&& r, Predicate&& p, F&& f)
{
    for(auto&& x : r)
    {
        if(p(x)) { f(x); }
    }
}

用法示例:

auto criteria = [](const int& i) -> bool { return (i % 2) == 0; };
for_items_matching(theList, criteria, [](auto&& item)
{
    std::cout << item << ", ";
})

通过一些重构和辅助类/函数,你可能会得到类似的结果:

for_items_of(theList)
    .matching(criteria)
    .execute([](auto&& item){ std::cout << item << ", "; });

另一种可能性是查看即将到来的Ranges TS

答案 1 :(得分:1)

如果我理解正确,那么您需要的是标准算法std::for_each_if。例如

#include <iostream>
#include <iterator>
#include <numeric>

template<class InputIterator, class Predicate, class Function>
Function for_each_if(InputIterator first,
                     InputIterator last,
                     Predicate predicate,
                     Function f)
{
    for (; first != last; ++first)
    {
        if (predicate(*first)) f(*first);
    }

    return f;
}

int main()
{
    int a[10];

    std::iota(std::begin(a), std::end(a), 0);

    for_each_if(std::begin(a), std::end(a),
        [](int x) { return x % 2 == 0;  },
        [](int x) { std::cout << x << ", "; });

    std::cout << std::endl;

    return 0;
}

程序输出

0, 2, 4, 6, 8,

然而实际上在C ++中没有这样的标准算法,尽管我建议将它包含在标准中。:)