范围拆分可以与谓词一起使用吗?
can ranges split be used with a predicate?
能否使用范围视图 split() 重写此双循环?
#include <vector>
#include <span>
struct MyPair
{
int a;
char b;
};
vector<MyPair> path = {{1,'a'},{1,'z'},{2,'b'},{2,'y'}};
vector<span<MyPair> > spans;
for (int i=0; i < path.size();)
{
auto r = path | ranges::views::drop(i) | views::take_while([&](const MyPair& p){return p.a == path[i].a;});
int size = ranges::distance(r);
span<Range> ranges(&path[i], size);
spans.push_back(ranges);
i += size ;
}
我想要一个看起来像
的视图
{{{1,'a'},{1,'z'}},{{2,'b'},{2,'y'}}}
Can this double loop be rewritten using ranges views split() ?
由于您没有使用范围作为分隔符来拆分原始范围,而是使用谓词来拆分范围,因此 views::split
实际上并没有解决问题。
然而,C++23采用了views::chunk_by
,根据[range.chunk.by.overview]中的描述:
chunk_by_view
takes a view
and a predicate, and splits the view into
subrange
s between each pair of adjacent elements for which the
predicate returns false
.
可以使用 views::chunk_by
和适当的谓词重写 for-loop:
vector<MyPair> path = ...
auto spans = path | std::views::chunk_by([](const auto& l, const auto& r) {
return l.a == r.a;
});
但是目前,没有编译器实现这个范围适配器,替代方案是使用 range-v3 的 views::group_by
.
值得注意的是ranges::views::group_by
在功能上不等同于std::views::chunk_by
:前者总是先比较[=41] =] 每个子范围中的元素与每个后续子范围中的元素,而后者总是比较 连续 个元素。
在没有 views::chunk_by 的情况下,这是我的代码,使用了一个很好的旧 for 循环:
#include <vector>
#include <span>
struct MyPair
{
int a;
char b;
};
vector<MyPair> path = {{1,'a'},{1,'z'},{2,'b'},{2,'y'}};
vector<span<MyPair> > spans;
int i_prev=0;
for (int i=0;i < path.size(); i++)
{
if (path[i].a != path[i_prev].a)
{
spans.push_back(span<MyPair>(&path[i_prev], i - i_prev));
i_prev=i ;
}
}
spans.push_back(span<MyPair>(&path[i_prev], path.size() - i_prev));
能否使用范围视图 split() 重写此双循环?
#include <vector>
#include <span>
struct MyPair
{
int a;
char b;
};
vector<MyPair> path = {{1,'a'},{1,'z'},{2,'b'},{2,'y'}};
vector<span<MyPair> > spans;
for (int i=0; i < path.size();)
{
auto r = path | ranges::views::drop(i) | views::take_while([&](const MyPair& p){return p.a == path[i].a;});
int size = ranges::distance(r);
span<Range> ranges(&path[i], size);
spans.push_back(ranges);
i += size ;
}
我想要一个看起来像
的视图{{{1,'a'},{1,'z'}},{{2,'b'},{2,'y'}}}
Can this double loop be rewritten using ranges views split() ?
由于您没有使用范围作为分隔符来拆分原始范围,而是使用谓词来拆分范围,因此 views::split
实际上并没有解决问题。
然而,C++23采用了views::chunk_by
,根据[range.chunk.by.overview]中的描述:
chunk_by_view
takes aview
and a predicate, and splits the view intosubrange
s between each pair of adjacent elements for which the predicate returnsfalse
.
可以使用 views::chunk_by
和适当的谓词重写 for-loop:
vector<MyPair> path = ...
auto spans = path | std::views::chunk_by([](const auto& l, const auto& r) {
return l.a == r.a;
});
但是目前,没有编译器实现这个范围适配器,替代方案是使用 range-v3 的 views::group_by
.
值得注意的是ranges::views::group_by
在功能上不等同于std::views::chunk_by
:前者总是先比较[=41] =] 每个子范围中的元素与每个后续子范围中的元素,而后者总是比较 连续 个元素。
在没有 views::chunk_by 的情况下,这是我的代码,使用了一个很好的旧 for 循环:
#include <vector>
#include <span>
struct MyPair
{
int a;
char b;
};
vector<MyPair> path = {{1,'a'},{1,'z'},{2,'b'},{2,'y'}};
vector<span<MyPair> > spans;
int i_prev=0;
for (int i=0;i < path.size(); i++)
{
if (path[i].a != path[i_prev].a)
{
spans.push_back(span<MyPair>(&path[i_prev], i - i_prev));
i_prev=i ;
}
}
spans.push_back(span<MyPair>(&path[i_prev], path.size() - i_prev));