【问题标题】:Find missing date in List<DateTime> and insert that date on the right index在 List<DateTime> 中查找缺失的日期并将该日期插入到正确的索引中
【发布时间】:2016-01-28 12:57:18
【问题描述】:

假设我有一个包含以下日期的列表。

List<DateTime> dateList = new List<DateTime>();
dateList.Add(new DateTime(2002, 01, 01));
dateList.Add(new DateTime(2002, 01, 02));
dateList.Add(new DateTime(2002, 01, 03));
dateList.Add(new DateTime(2002, 01, 04));
dateList.Add(new DateTime(2002, 01, 06));
dateList.Add(new DateTime(2002, 01, 08));

如何遍历 dateList,找到缺少的 DateTimes(2002-01-05 和 2002-01-07),然后创建这些 DateTimes 并将它们添加到正确索引上的 dateList 中?

【问题讨论】:

  • 一个选项是生成一个缺少日期的新列表。这是一个选择吗?
  • 避免SortedList有什么意义吗?
  • 我能够提取缺失的日期,但不确定如何将它们插入到 dateList 中的正确索引上。

标签: c# .net datetime for-loop foreach


【解决方案1】:

您可以使用以下方法确定最小和最大日期以及 TimeSpan 差异,然后生成列表:

DateTime min = dateList.Min();
DateTime max = dateList.Max();
TimeSpan diff = max - min;
dateList = Enumerable.Range(0, diff.Days + 1).Select(d => min.AddDays(d)).ToList();

您需要使用diff.Days + 1 来包含结束日期。

如果由于某种原因不能使用 LINQ,则可以使用 for 循环和 List.Insert,但如果不确定列表是否已排序,则必须事先使用 List.Sort

dateList.Sort();
if (dateList.Count > 1)
{
    for (int i = 0; i < dateList.Count - 1; i++)
    {
        DateTime currrent = dateList[i].Date;
        DateTime next = dateList[i + 1].Date;
        DateTime expected = currrent.AddDays(1);
        if (next != expected)
        {
            dateList.Insert(++i, expected);
        }
    }
}

您会看到 LINQ 版本的可读性提高了多少。

【讨论】:

  • @bensij:编辑了我的答案,以提供一种非 LINQ 方法来展示没有 LINQ 的世界会有多灰暗。
【解决方案2】:

这里的想法是循环查找缺失的日期,并将其添加到新列表中。最后,加入两个列表并按日期重新排序。不是最好的性能,但易于理解/维护。

var dates = new List<DateTime>();
dates.Add(new DateTime(2002, 01, 01));
dates.Add(new DateTime(2002, 01, 02));
dates.Add(new DateTime(2002, 01, 03));
dates.Add(new DateTime(2002, 01, 04));
dates.Add(new DateTime(2002, 01, 06));
dates.Add(new DateTime(2002, 01, 08));

// algo works only if dates are in order
dates = dates.OrderBy(date => date).ToList();

var missingDates = new List<DateTime>();
for (int i = 0; i + 1 < dates.Count; i++)
{
    var diff = (dates[i + 1] - dates[i]).TotalDays;
    for(int iToComplete = 1; iToComplete < diff; iToComplete++)
    {
        missingDates.Add(dates[i].AddDays(iToComplete));
    }
}
dates.AddRange(missingDates);
dates = dates.OrderBy(date => date).ToList();

【讨论】:

  • 谢谢!很高兴看到不同的解决方法:)
【解决方案3】:

当您有开始和结束日期时,您可以生成所有日期的列表。然后使用Except 查找原始列表中缺少的日期:

var startDate = dateList.Min();
var endDate = dateList.Max();

var allDates = Enumerable.Range(0, (endDate - startDate).Days)
                         .Select(i => startDate.AddDays(i));

var missingDates = allDates.Except(dateList);

缺少日期:

2002 年 1 月 5 日
2002 年 1 月 7 日

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多