改进分区算法

Improve partitioning algorithm

我正在尝试编写一种算法,该算法使用开始日期和结束日期以及增量来构建日期范围数组。

从广义上讲,算法的输入和输出如下:

/*
    INPUT : T1 of type DateTimeoffset.
            T2 of type DateTimeoffset.
            delta of type Int.
        
    OUTPUT : An array of time ranges [x, y] where x is start date and y is end date.
    
    R1 = [T1             , T1 + delta * 1]
    R2 = [T1 + delta * 1 , T1 + delta * 2]
    R3 = [T1 + delta * 2 , T1 + delta * 3]
    R4 = [T1 + delta * 3 , T1 + delta * 4]
    R5 = [T1 + delta * 4 , T1 + delta * 5]
    R6 = [T1 + delta * 5 , T2]
*/  

我为此构建的C#代码如下:

public static (DateTimeOffset From, DateTimeOffset To)[] Partition(DateTimeOffset start, DateTimeOffset end, int delta)
{
    var ranges = new List<(DateTimeOffset From, DateTimeOffset To)>();
    var lower = start;

    var offset = 0;

    while (lower < end)
    {
        var lowerbound = start + TimeSpan.FromMinutes(delta * offset);
        var upperbound = start + TimeSpan.FromMinutes(delta * ++offset);

        if(upperbound > end)
            upperbound = end;

        ranges.Add((From: lowerbound, To: upperbound));

        lower = upperbound;
    }

    return ranges.ToArray();
}

是否有更好的方法来编写此算法?如果没有,如何改进?

看来你不需要每次都乘以偏移量,只需跟踪之前的上限即可:

public static (DateTimeOffset From, DateTimeOffset To)[] Partition(DateTimeOffset start, DateTimeOffset end, int delta)
{
    var ranges = new List<(DateTimeOffset From, DateTimeOffset To)>();
    var lowerbound = start;
    
    while (lowerbound < end)
    {
        var upperbound = lower + TimeSpan.FromMinutes(delta);
        
        if(upperbound > end) upperbound = end;
        
        ranges.Add((From: lowerbound, To: upperbound));
        
        lowerbound = upperbound;
    }
    
    return ranges.ToArray();
}

其他选项:

  • 您需要 return 数组吗?您能否仅 return 列表或 IEnumerable 并避免(相对便宜)转换为数组?
  • 您可以在计算时使用 yield 到 return 值,但唯一的好处是如果消费者不需要整个列表并且可以在生成结束之前停止生成.