来自 RangeOfRanges 的范围

Ranges from RangeOfRanges

在 D 中,您可以执行以下操作来创建数组元素的成对元组:

auto a = [0, 1, 2, 3, 4];
auto x = a.zip(a.save.dropOne);

x 现在可以扩展为 [[0, 1], [1, 2], [2, 3], [3, 4]]

我想概括这个概念来创建这样的 n 元组:

auto i = 0;
auto x = zip(generate!(() => a.save.dropExactly(i++)).take(n));

然而,这导致 x 成为 Tuple!([1, 2, 3, 4]), Tuple!([2, 3, 4]) 的范围,因为 n = 2。

这是合理的,因为 take 产生了子范围。但是我如何创建单独的范围来实现预期的行为?

提前致谢。

如果我没理解错的话,您正在寻找类似 slide 的内容。它已经是 Phobos 的一部分,将包含在下一个版本 (2.076.0) 中:

assert([0, 1, 2, 3].slide(2).equal!equal(
    [[0, 1], [1, 2], [2, 3]]
));
assert(5.iota.slide(3).equal!equal(
    [[0, 1, 2], [1, 2, 3], [2, 3, 4]]
));

但是,请注意,对于随机访问范围,很容易实现开箱即用的滑动 window 迭代器:

import std.range, std.stdio;
void main(string[] args)
{
    auto arr = 5.iota;
    auto n = 2;
    // Plain D arrays & slices
    foreach (i; 0 .. arr.length - n + 1)
        arr[i .. i + n].writeln;
    // [0, 1], [1, 2], [2, 3], [3, 4]

    // As a range
    arr = 10.iota;
    n = 3;
    int k = 0;
    generate!(() => arr[k .. k++ + n]).take(3).writeln;
    // [[0, 1, 2], [1, 2, 3], [2, 3, 4]]

    n = 4, k = 0;
    generate!(() => arr[k .. k++ + n]).take(3).writeln;
    // [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
}

Play with this example online.