清洁循环以匹配元素

Clean for loop for matching elements

本文关键字:元素 循环 清洁      更新时间:2023-10-16

我发现我编写的许多代码一般都遵循"循环穿过此容器的循环,并且对符合某些标准的元素进行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

有更好的方法吗?

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

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 << ", "; });

另一种可能性是查看即将到来的范围TS。

如果我正确理解您,那么您需要的是标准算法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 中没有这种标准算法,尽管我提出了一个建议将其包括在标准中。:)