C++ "group where"算法

C++ "group where" algorithm

本文关键字:算法 where group C++      更新时间:2023-10-16

STL中是否有一个函数可以将序列划分为连续的子序列,其中某些谓词是有效的?

例如,以下序列:

1 1 1 0 1 1 0 0 1 1 1 1

给定一个谓词v == 1,应该返回三个子序列:

1 1 1
1 1
1 1 1 1

应保留组的顺序以及这些组内的元素。

我可以在 O(N) 中编写一个循环来执行此操作,但我正在尝试了解有关 STL 的更多信息并避免此类事情的循环。肖恩·帕伦特(Sean Parent)的精彩演讲,C++调味料,是我的动力。

翻看<algorithm>,什么都没有向我跳出来。

标准库中还没有这样的算法。您可以使用std::find_ifstd::find_if_not手写一个,以查找每个出现序列的开始和结束迭代器。我认为输出应该是std::pair<FwdIt, FwdIt>范围.该算法的输入O(N)复杂性。

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <utility>
template<class FwdIt, class OutIt, class UnaryPred>
auto find_all_if(FwdIt first, FwdIt last, OutIt dst, UnaryPred pred)
{   
    while (first != last) {
        // start of next occurance
        auto next_b = std::find_if(first, last, pred);
        if (next_b == last) break;
        // end of next occurance
        auto next_e = std::find_if_not(next_b, last, pred);
        *dst++ = make_pair(next_b, next_e);
        first = next_e;
    }
    return dst;
}
int main()
{
    auto const v = std::vector<int> { 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1 };
    using It = decltype(v.begin());
    std::vector<std::pair<It, It>> r; // "range of ranges" 
    find_all_if(begin(v), end(v), std::back_inserter(r), 
        [](auto e) { return e == 1; }
    );
    for (auto&& e : r) {
        std::cout << "[";
        std::cout << std::distance(begin(v), e.first) << ", ";
        std::cout << std::distance(begin(v), e.second) << "), ";
    }
}

C++14 样式的实时示例(使用手动类型定义和函数对象来打印[0, 3), [4, 6), [8, 12)的良好 ole C++98)。

算法应该返回什么?范围向量(迭代器对)?还是应该只留下一个修改过的容器,其不符合标准的元素应该被删除?

对于第一种情况,您可以"半手"完成:使用交替std::find_if()std::find_if_not()直到到达容器的末端。

对于第二种情况,应用删除-擦除-习惯用法。

container.erase( std::remove_if(
        std::begin( container ), std::end( container ), 
        []( int i ){ return i != 1; } ), 
    std::end( container ) );