使用 LINQ 用最新的可用值填充列表
Using LINQ to fill the list with the latest available value
我有一个数据对象
- 某个报告的公布日期,
- 以及当时公布的价值
即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
};
}
}
这个解决方案非常简单、可读和可维护。您甚至不必修改当前代码即可使用此功能。稍后您可以使用分析器查看是否存在性能问题并轻松改进此代码(预防性排序、缓存等)。
这当然不是你问题的答案,但它可能会帮助你意识到,也许你正在尝试解决一个不存在的问题。
我有一个数据对象
- 某个报告的公布日期,
- 以及当时公布的价值
即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
};
}
}
这个解决方案非常简单、可读和可维护。您甚至不必修改当前代码即可使用此功能。稍后您可以使用分析器查看是否存在性能问题并轻松改进此代码(预防性排序、缓存等)。
这当然不是你问题的答案,但它可能会帮助你意识到,也许你正在尝试解决一个不存在的问题。