Generics 前向差分算法

Generics 前向差分算法,generics,range,d,forward,difference,Generics,Range,D,Forward,Difference,std.algorithm或std.range中是否有函数用于延迟计算正向差?我需要它在一个范围内对排序元素(整数)进行差异打包。整数正好是SysTime时间戳 更新:建议的解决方案: /** Compute Forward Difference of $(D range). */ auto ref forwardDifference(bool reverse = false, Range)(in Range range) @safe pure nothrow if (isInputR

std.algorithm
std.range
中是否有函数用于延迟计算正向差?我需要它在一个范围内对排序元素(整数)进行差异打包。整数正好是
SysTime
时间戳

更新:建议的解决方案:

/** Compute Forward Difference of $(D range).
 */
auto ref forwardDifference(bool reverse = false, Range)(in Range range)
    @safe pure nothrow if (isInputRange!Range)
{
    import std.algorithm: map;
    import std.range: zip, dropOne;
    static if (reverse)
        return range.zip(range.dropOne).map!(a => a[1] - a[0]);
    else
        return range.zip(range.dropOne).map!(a => a[0] - a[1]);
}

unittest {
    const i = [1, 5, 9, 17];
    import std.algorithm: equal;
    assert(equal(i.forwardDifference!false, [ -4, -4, -8]));
    assert(equal(i.forwardDifference!true,  [ +4, +4, +8]));
}

请对解决方案发表意见。

如果我理解正确,您的意思是这样的吗

auto i = [1, 5, 9, 17];
writeln(i.zip(i.dropOne()).map!(a=>a[0] - a[1]));

另一种方法是制作自己的系列:

import std.range;
import std.stdio;

auto forwardDifference(Range)(Range r) if (isInputRange!Range)
{
    struct ForwardDifference
    {

        Range range;
        alias ElementType!Range E;
        E _front;
        bool needInitialize = true;

        this (Range range)
        {
            this.range = range;
        }

        E front()
        {
            if (needInitialize)
            {
                popFront();
            }
            return _front;
        }

        E moveFront()
        {
            popFront();
            return _front;
        }

        void popFront()
        {
            if (empty is false)
            {
                needInitialize = false;
                E rf = range.front;
                range.popFront();
                if (range.empty is false)
                {
                    _front = rf - range.front;
                }
            }
        }

        bool empty()
        {
            return range.empty;
        }
    }

    return ForwardDifference(r);
}
void main(string[] args)
{
    auto i = [1, 2, 3, 5, 7, 9];
    writeln(i.forwardDifference);
    stdin.readln;
}

注意,给定
E
,当
e-e
e
本身的类型不同时,这不起作用,例如当
e
std.datetime.SysTime
时,它的差异变为
Duration
类型,并且该算法无法实例化。这是一个更正的版本

auto forwardDifference(Range)(Range r) if (isInputRange!Range) {
import std.range: front, empty, popFront;

struct ForwardDifference {
    Range _range;
    alias E = ElementType!Range;
    typeof(_range.front - _range.front) _front;
    bool _needInitialize = true;

    this (Range range) { this._range = range; }

    auto ref front() {
        if (_needInitialize) { popFront(); }
        return _front;
    }

    auto ref moveFront() {
        popFront();
        return _front;
    }

    void popFront() {
        if (empty is false) {
            _needInitialize = false;
            E rf = _range.front;
            _range.popFront();
            if (_range.empty is false)
            {
                _front = _range.front - rf;
            }
        }
    }

    bool empty() { return _range.empty; }
}

return ForwardDifference(r);
}


现在自然的问题是:我们应该在什么时候创建新的专门范围,比如这个范围,以及我们应该在什么时候重用和重新组合
std.range

中的现有范围。甚至比当时的变种还要短。如果我们删除
writeln
并使其成为一个函数,您的版本会返回一个延迟的求值范围,对吗?请参见此处是否确实需要使用
zip