如何使用 range-v3 逐对转换范围?

问题描述 投票:0回答:3

我正在编写一个算法来消除重叠,给定一定范围的线(我将其称为“线”,因为在这种情况下术语“范围”含糊不清)。

这就是

line
的样子:

struct line {
   int begin, width;
   int end() const { return begin + width; }
};

示例:给定三行 (0,3)、(1,2) 和 (5,1),我期望在转换后获得 (0,3)、(3,2) 和 (5,1)。这是这个问题的图形表示:

Overlap Removal

这是该问题的一种可能的解决方案:

auto removeOverlap(std::pair<line, line> input)
{
    // keeps first line untouched and shifts the second line to the end of the first one, if necessary
    return std::pair<line, line>{std::get<0>(input), {std::max(std::get<0>(input).end(), std::get<1>(input).begin), std::get<1>(input).width}};
}

int main(int argc, char *argv[])
{

    std::array<line, 3> lines{{{0,3},{1,2},{5,1}}};
    for(int i = 0; i < lines.size()-1; ++i)
    {
        std::tie(lines[i], lines[i+1]) = removeOverlap(std::make_pair(lines[i], lines[i+1]));
    }
    assert(lines[0].begin == 0);
    assert(lines[1].begin == 3);
    assert(lines[2].begin == 5);

我的问题:我如何使用 range-v3 来做到这一点?

我正在考虑使用修改后的

view::chunk(N)
,其中增量的大小为1(而不是N)。但我真的不知道如何从这一点开始。

c++ c++11 c++14 range-v3
3个回答
3
投票

你可以这样做:

auto pair_view =
    ranges::view::zip(lines | ranges::view::take(lines.size() - 1),
                      lines | ranges::view::drop(1));

for (auto&& p : pair_view)
{
    p = removeOverlap(p);
}

演示


1
投票
auto push_highwater = [](int& highwater){
  return [&](line l) {
    l.begin = (std::max)(highwater, l.begin);
    highwater = l.end();
    return l;
  };
};

将其提供给原始范围的变换视图,然后按顺序迭代变换后的视图。

从最小整数的最高水位开始。 确保 int 寿命足够长。

实例(无法找到一种更简单的方法将数组转换回自身......)


0
投票
namespace rv = ranges::views;
auto pairsView = rv::zip(lines | rv::drop_last(1), lines | rv::drop(1));
© www.soinside.com 2019 - 2024. All rights reserved.