在DayOfWeek列表中查找最近一周的日期

这可能是一个新手问题,但在这里。

我有一种方法,其中的DayOfWeek列表会附上一周中的不同日子(可能是星期三和星期六,星期日,星期一和星期五等)。

鉴于该列表,我需要将它与Datetime参数进行比较,找到Day Day参数在DayOfWeek列表中最接近的日期,并根据它在列表中的哪个Week Day将Date添加到DateTime参数。

例如,如果传入的DateTime参数是星期日,并且我的DayOfWeek列表包含星期三和星期六,则该参数需要移回到星期六,因为它在列表中最接近。

同样,如果我的列表包含星期日,星期一和星期六,并且传入的参数是星期四,那么参数将不得不移至星期六。

最后,如果参数与列表中的两个星期的日期等距(星期三传入,星期一和星期五在列表中或星期日传入,星期二和星期五在列表中),则参数需要向前移动到下一个最近的一周(第一个例子是星期五,第二个例子是星期二)。

这将是理想的(至少对我来说),将下一个最接近的一周的距离从传入的日期转换为一个int,这样我可以执行如下操作:

passedInDate = passedInDate.AddDays(dayOfWeekDistance);
return passedInDate;

但我愿意接受建议。

我已经尝试了LINQ语句,例如:

int dayOfWeekDistance = targetDayOfWeekList.Min(x => (x - passedInDate));

但无济于事。 必须有一些我错过的奇特的LINQ语句。

只是一个头向上,我无法工作的主要项目是从星期天返回到星期六,如果传入日期是星期日,并且列表中最近的星期几是星期六(同样,如果传入日期是星期一,最近一周是星期五,日期需要一直返回到星期五)。

请让我知道,如果我错过了什么,或者我只是没有道理。

欢迎所有帮助! 谢谢。


通过辅助函数,可以使用LINQ。

帮助函数使用效用函数计算一周中最近的一天来计算两个DOW之间的前向天数:

public int MinDOWDistance(DayOfWeek dow1, DayOfWeek dow2) {
    int FwdDaysDiff(int idow1, int idow2) => idow2 - idow1 + ((idow1 > idow2) ? 7 : 0);
    int fwd12 = FwdDaysDiff((int)dow1, (int)dow2);
    int fwd21 = FwdDaysDiff((int)dow2, (int)dow1);
    return fwd12 < fwd21 ? fwd12 : -fwd21;
}

然后,您可以在列表中找到最近的DOW,并返回使用Aggregate with LINQ移动(和方向)的正确天数:

public int DaysToClosestDOW(DayOfWeek dow1, List<DayOfWeek> dowList) {
    return dowList.Select(dow => {
                                    var cdow = MinDOWDistance(dow1, dow);
                                    return new { dow, dist = cdow, absdist = Math.Abs(cdow) };
                                 })
                  .Aggregate((g1, g2) => (g1.absdist < g2.absdist) ? g1 : ((g1.absdist == g2.absdist) ? ((g1.dist > 0) ? g1 : g2) : g2)).dist;
}

它发生在我身上,我可以使用一个元组来从辅助函数返回absdist ,因为它已经知道它。 然后我可以在LINQ中使用Tuple

public (int dist, int absdist) MinDOWDistance(DayOfWeek dow1, DayOfWeek dow2) {
    int FwdDaysDiff(int idow1, int idow2) => idow2 - idow1 + ((idow1 > idow2) ? 7 : 0);
    int fwd12 = FwdDaysDiff((int)dow1, (int)dow2);
    int fwd21 = FwdDaysDiff((int)dow2, (int)dow1);
    if (fwd12 < fwd21)
        return (fwd12, fwd12);
    else
        return (-fwd21, fwd21);
}

public int DaysToClosestDOW(DayOfWeek dow1, List<DayOfWeek> dowList) {
    return dowList.Select(dow => MinDOWDistance(dow1, dow))
                  .Aggregate((g1, g2) => (g1.absdist < g2.absdist) ? g1 : ((g1.absdist == g2.absdist) ? ((g1.dist > 0) ? g1 : g2) : g2)).dist;
}

让问题分成几个小部分。

注意:以下所有方法都应该放在类似这样的类中

public static class DayOfWeekExtensions
{
}

首先,您希望Sunday成为本周的最后一天,而在DayOfWeek enum它首先定义。 所以让我们来说明一个函数:

public static int GetIndex(this DayOfWeek source)
{
    return source == DayOfWeek.Sunday ? 6 : (int)source - 1;
}

然后我们需要一个函数来计算两个DayOfWeek值之间的距离(偏移量):

public static int OffsetTo(this DayOfWeek source, DayOfWeek target)
{
    return source.GetIndex() - target.GetIndex();
}

我们还需要添加一个给定主键的函数,并且两个DayOfWeek值选择两个值中最接近的值(应用您的优先级规则):

public static DayOfWeek Closest(this DayOfWeek pivot, DayOfWeek first, DayOfWeek second)
{
    int comp = Math.Abs(first.OffsetTo(pivot)).CompareTo(Math.Abs(second.OffsetTo(pivot)));
    return comp < 0 || (comp == 0 && first.GetIndex() > pivot.GetIndex()) ? first : second;
}

现在我们准备实施从序列中找到最近的日子的方法。 它可以用很多方式实现,这里是使用(finally!:) LINQ Aggregate方法的实现:

public static DayOfWeek? Closest(this IEnumerable<DayOfWeek> source, DayOfWeek target)
{
    if (!source.Any()) return null;
    return source.Aggregate((first, second) => target.Closest(first, second));
}

最后,让我们添加一个计算最近距离的函数:

public static int ClosestDistance(this IEnumerable<DayOfWeek> source, DayOfWeek target)
{
    return source.Closest(target)?.OffsetTo(target) ?? 0;
}

我们完成了。 我们只创建了一个简单的可重用实用程序类。

你的情况的用法是:

int dayOfWeekDistance = targetDayOfWeekList.ClosestDistance(passedInDate.DayOfWeek);

更新:事实证明,您的要求是不同的。

应用相同的原则,首先我们需要一个函数来计算一周中两天之间的前后距离的最小值,应用前向优先规则。

public static int MinDistanceTo(this DayOfWeek from, DayOfWeek to)
{
    int dist = to - from;
    return dist >= 4 ? dist - 7 : dist <= -4 ? dist + 7 : dist;
}

它的作用主要是将值从可能的转换-6..6包容范围值在-3..3包含的范围。

然后我们只需要一个函数,它将通过使用Select + Aggregate (它也可以用Min和自定义比较器实现)来实现有问题的方法。 它基本上比较两个绝对距离,并再次应用正向优先规则:

public static int MinDistanceTo(this DayOfWeek from, IEnumerable<DayOfWeek> to)
{
    if (!to.Any()) return 0;
    return to.Select(x => from.MinDistanceTo(x)).Aggregate((dist1, dist2) =>
    {
        if (dist1 == dist2) return dist1;
        int comp = Math.Abs(dist1).CompareTo(Math.Abs(dist2));
        return comp < 0 || (comp == 0 && dist1 > 0) ? dist1 : dist2;
    });
}

用法如下:

int dayOfWeekDistance = passedInDate.DayOfWeek.MinDistanceTo(targetDayOfWeekList);
链接地址: http://www.djcxy.com/p/54893.html

上一篇: Find Closest Week Day in DayOfWeek List

下一篇: Algorithm to group messages by time