将分割范围划分为重叠范围
问题描述:
我试图使用Ranges-V3库将一个容器值切片到一系列范围内,以使相邻范围共享边界元素。将分割范围划分为重叠范围
考虑以下几点:
using namespace ranges;
std::vector<int> v = { 1, 2, 3, 0, 4, 0, 5, 0, 6, 7, 8, 0, 0, 9 };
auto myRanges = v | /* something like adjacent split */
for_each(myRanges, [](auto&& range){ std::cout << range << std::endl;});
我想的范围内划分成基于重叠子范围的区域是否fullfills两个标准:所述元件
- 是否具有零
- 的值或者与一个或多个值为零的元素相邻
所需的输出:
[1,2,3]
[3,0,4,0,5,0,6]
[6,7,8]
[8,0,0,9]
我尝试:
auto degenerate =
[](auto&& arg){
return distance(arg) < 2;
};
auto myRanges = v | view::split(0) | view::remove_if(degenerate);
for_each(myRanges, [](auto&& range){ std::cout << range << std::endl;});
输出:
[1,2,3]
[6,7,8]
我茫然的我怎么可能
- “插入” 的范围从3到6
- “追加” 的范围从8到9
答
如果我正确理解你的要求,那么你可以在adjacent_find
方面实现发电机:
template<typename IterT>
struct seg_generator_ {
IterT it_, end_;
bool fz_ = true;
ranges::iterator_range<IterT> operator()() {
if (it_ == end_) {
return {it_, end_};
}
auto n = ranges::adjacent_find(
it_, end_,
[fz = std::exchange(fz_, !fz_)](auto const a, auto const b) {
return a && !b == fz;
}
);
return {
std::exchange(it_, n),
n != end_ ? ranges::next(std::move(n)) : std::move(n)
};
}
};
template<typename RngT>
auto seg_generator(RngT&& rng) -> seg_generator_<decltype(ranges::begin(rng))> {
return {ranges::begin(rng), ranges::end(rng)};
}
int main() {
std::vector<int> const v{1, 2, 3, 0, 4, 0, 5, 0, 6, 7, 8, 0, 0, 9};
auto myRanges =
ranges::view::generate(seg_generator(v))
| ranges::view::take_while([](auto const& r) { return !r.empty(); });
ranges::copy(myRanges, ranges::ostream_iterator<>{std::cout, "\n"});
}
不完全如人们所希望的那样简洁...: - [
你为什么通过移动参考?它会破坏你的数据 – Sugar
@Sugar我假设你指的是'auto &&'的使用以及'&&'暗示右值引用的印象。在这种情况下,该sigil并不意味着右值引用,而是Scott Meyer所称的通用引用。查看更多(这里)[https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers] – apmccartney
[Here](https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers)是apmccartney链接的工作版本。 –