使用 LINQ 用最新的可用值填充列表

Using LINQ to fill the list with the latest available value

我有一个数据对象

  1. 某个报告的公布日期,
  2. 以及当时公布的价值

即class 看起来像:

    class Report
    {
    DateTime announcementDate;
    double ValueAnnounced;
    }

因此,考虑具有以下值的 Report 列表:

    List<Report> reports = new List<Report>;
    Report newReport = new Report();
    newReport.announcementDate =Convert.ToDateTime("1/1/2011"); newReport.ValueAnnounced = 5;reports.Add(newReport);
    newReport.announcementDate = Convert.ToDateTime("2/1/2011"); newReport.ValueAnnounced = 10;reports.Add(newReport);
    newReport.announcementDate = Convert.ToDateTime("3/1/2011"); newReport.ValueAnnounced = 15;reports.Add(newReport);

现在,我需要的是,我需要创建一个新列表"that will have the latest value announced for each of the calendar date from 1/1/2011 to 3/31/2011."

即linq 将 return 一个包含以下元素的列表:

    dailyReport[0].calendarDate = 1/1/2011; dailyReport[0].latestValue = 5;
    dailyReport[1].calendarDate = 1/2/2011; dailyReport[2].latestValue = 5;
    dailyReport[2].calendarDate = 1/3/2011; dailyReport[3].latestValue = 5;
    ...
    ...
    ...
    dailyReport[30].calendarDate = 2/1/2011; dailyReport[30].latestValue = 10;
    dailyReport[31].calendarDate = 2/2/2011; dailyReport[31]latestValue = 10;
    dailyReport[32].calendarDate = 2/3/2011; dailyReport[32].latestValue = 10;
    dailyReport[33].calendarDate = 2/4/2011; dailyReport[33].latestValue = 10;
    ...
    ...
    ...
    dailyReport[60].calendarDate = 3/1/2011; dailyReport[60].latestValue = 15;
    dailyReport[61].calendarDate = 3/2/2011; dailyReport[61].latestValue = 15;
    dailyReport[62].calendarDate = 3/3/2011; dailyReport[62].latestValue = 15;
    ...
    ...
    ...
    dailyReport[90].calendarDate = 3/31/2011; dailyReport[62].latestValue = 15;        

我已经可以在这个循环的帮助下生成 dailyReport 列表:

    List<Report> dailyReport = new List<Report>;


    foreach (DateTime calendarDay in EachDay(StartDate, EndDate))
    {
            var latestAvailableReport =
                (
                from theReport in reports
                where theReport.announcementDate <= calendarDay
                orderby theReport.announcementDate descending
                select theReport
                ).ToList();

            Report newDailyReport = new Report();
            newDailyReport.announcementDate = latestAvailableReport[0].announcementDate;
            newDailyReport.ValueAnnounced = latestAvailableReport[0].ValueAnnounced;
            dailyReport.Add(newDailyReport);

    }

支持方法 EachDay 如下所示:

    public IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
    {
        for(var day = from.Date; day.Date <= thru.Date; day =day.AddDays(1))
        yield return day;
    }

然而,我的问题是,我可以感觉到应该有更快(或至少更优雅)的方法来生成 dailyReport 列表——这基本上是原始列表的 "fill in with latest value" 版本。

我认为这种优雅的方式显然是一种巧妙的 LINQ 设计 - 以我目前的知识和能力我无法理解。

你能帮我写下那个 LINQ 吗?

在此先感谢您的关注和时间,非常感谢。

艾库特·萨里比耶克

你想达到什么目的?你问的是如何为你的问题编写好的代码,但没有好的代码本身,它总是有一些好处:性能、内存使用、可读性和可维护性等。

你现在在做什么,你在努力提高性能,但让内存使用和可维护性变得更糟。

如果我是你,我会先这样写代码:

public static class ReportListExtensions
{
    public static Report GetReport(this IEnumerable<Report> reports, DateTime date)
    {
        return new Report
        {
            AnnouncementDate = date,
            ValueAnnounced = reports.OrderByDescending(r => r.AnnouncementDate)
                                    .First(r => r.AnnouncementDate < date)
                                    .ValueAnnounced
        };
    }
}

这个解决方案非常简单、可读和可维护。您甚至不必修改当前代码即可使用此功能。稍后您可以使用分析器查看是否存在性能问题并轻松改进此代码(预防性排序、缓存等)。

这当然不是你问题的答案,但它可能会帮助你意识到,也许你正在尝试解决一个不存在的问题。