C#有一种更快的方法来获得日期设置之间的最大差异而不是循环

时间:2017-06-29 18:54:37

标签: c# .net algorithm visual-studio

我有一个按降序排列的日期列表,例如

var dates = {date1, date2, date3};

任务是查找日期之间的最大天数。

到目前为止,我所做的是:

var maxDays = 0;
var previousDate = dates.First();
foreach (var thisDate in dates.Skip(0)) 
{
    maxDays = Max(thisDate - previousDate,  maxDays);
    previousDate = thisDate;
} 

这样可以正常工作,直到我在列表中获得大约1000个以上的日期。

你能推荐其他方法吗?

谢谢

2 个答案:

答案 0 :(得分:4)

我建议采用略有不同的方法:

 HashSet<TimeSpan> counts = new HashSet<TimeSpan>();
 var previousDate = dates.First();
 foreach (var thisDate in dates.Skip(1))
 {
      counts.Add(previousDate - thisDate);
      previousDate = thisDate;
 }
 var max = counts.Max();

我们的想法是不计算每次迭代的最大值,而是收集差异,然后让Max成为一个设定的操作。

使用HashSet还可以减少您将要检查的[唯一]差异的数量。

我用200,000个日期测试了它,花了不到300毫秒。

答案 1 :(得分:2)

假设datesList<DateTime>,你可以运行一个以第一个元素开头的循环,直到倒数第二个元素。然后在循环内部,将当前元素与下一个元素进行比较,如果差异大于当前最大值,则重置它:

double maxDays = 0;
for (int i = 0; i < dates.Count - 1; i++)
{
    var diff = (dates[i + 1] - dates[i]).TotalDays;
    if (diff > maxDays ) maxDays  = diff;
}

这是一项基准测试,显示处理100万件物品需要大约10毫秒时间:

private static void Main()
{
    var numDates = 1000000;
    var dates = new List<DateTime>();

    // initialize list with random dates
    var rnd = new Random();
    for (int i = 0; i < numDates; i++)
    {
        var day = rnd.Next(1, 29);
        var month = rnd.Next(1, 13);
        var year = rnd.Next(DateTime.MinValue.Year, DateTime.MaxValue.Year + 1);

        dates.Add(new DateTime(year, month, day));
    }

    // Sort the list descending
    dates = dates.OrderByDescending(d => d).ToList();

    // find the two neighbors with the greatest distance
    double maxDays = 0;
    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < dates.Count - 1; i++)
    {
        var diff = (dates[i] - dates[i + 1]).TotalDays;
        if (diff > maxDays) maxDays = diff;
    }
    sw.Stop();

    // Display results
    Console.WriteLine($"The greatest difference was {maxDays} days.");
    Console.WriteLine($"The comparison of {dates.Count} items took {sw.ElapsedMilliseconds} milliseconds");

    Console.WriteLine("\nDone!\nPress any key to exit...");
    Console.ReadKey();
}

<强>输出

enter image description here