C++ C++&引用;组,其中;算法

C++ C++&引用;组,其中;算法,c++,algorithm,c++11,stl,C++,Algorithm,C++11,Stl,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的知识,并避免这种类型的循环。肖恩家长的精彩演讲,是我的动力 通过查看,我什么也没想到。算法应该返回什么?范围向量(迭代器对)?或者它应该只留下一个修改过的容器,其中不满足标准

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的知识,并避免这种类型的循环。肖恩家长的精彩演讲,是我的动力


通过查看
,我什么也没想到。

算法应该返回什么?范围向量(迭代器对)?或者它应该只留下一个修改过的容器,其中不满足标准的元素应该被删除

对于第一种情况,您可以“半手工”完成:使用交替,直到您到达容器的末端

对于第二种情况,应用


标准库中还没有这样的算法。您可以使用
std::find_if
std::find_if_not
手动编写一个,以查找每个发生序列的开始和结束迭代器。我认为输出应该是
std::pair
的范围。该算法在其输入上具有
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) << "), ";
    }
}

#包含在打印
[0,3]、[4,6]的C++14样式中(对好的ole C++98使用手动类型定义和函数对象),[8,12)
用于您的输入。

也许这个问题也可以表示为一种更通用的标记化形式?在您的示例中,分隔符满足v!=1。使用
std::partition\u point
std::stable\u partition
是否可能?我不清楚:“应该返回三个子序列”子序列应该如何返回?数组视图向量?迭代器?容器中的迭代器?范围向量?@Ali,我也一直在想这个问题。我不知道什么是最实用或最惯用的。我会投票选择“集合”最符合STL的范围。第二个解决方案不符合要求。@user2672165为什么不?对我来说,晚上可能太晚了,但你不是只能从中得到一个范围吗?这是正确的。从这个问题来看,我不清楚计算结果到底应该是什么。这是一个更简单的选择。我想这已经足够好了。是否有任何算法可以从中获得多个范围?@user2672165否,当前的标准算法和容器成员函数要么不返回任何内容,要么返回一个计数、一个迭代器,要么返回一对迭代器和bool(例如
map::insert
)。当然,将迭代器返回到迭代器对的输出范围中是在模拟您请求的范围。好的。感谢您提供的信息。另外,您可能会想到,尽管范围对于STL非常重要,但没有正式类型(def)对于一个范围。在您的情况下,您必须配对。@user2672165请查看讨论这些主题的位置。最近有很多讨论。
#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) << "), ";
    }
}