C++ C++&引用;组,其中;算法
STL中是否有一个函数可以将一个序列划分为连续的子序列,其中某些谓词是有效的 例如,以下顺序: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的知识,并避免这种类型的循环。肖恩家长的精彩演讲,是我的动力 通过查看,我什么也没想到。算法应该返回什么?范围向量(迭代器对)?或者它应该只留下一个修改过的容器,其中不满足标准
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) << "), ";
}
}