使用类似的东西:
IList<DateTime> dates =
this.DateRanges
.SelectMany(r => new [] { r.From, r.To })
.Distinct()
.OrderBy(d => d)
.ToList();
Run Code Online (Sandbox Code Playgroud)
我可以获得所有日期,而不会重复任何日期.范围可以完全重叠,部分重叠(上部或下部重叠),触摸或它们可以根本不重叠.
现在我需要将此列表转换为另一个列表,以便每个连续日期对DateTime在对中间形成一个新生成的实例
D1 D2 D3 D4 D5
G1 G2 G3 G4
Run Code Online (Sandbox Code Playgroud)
其中D n是我与列表中不同的日期,而G m日期是我想在其中间生成的日期.
如何将各个日期的有序列表转换为对,以便我得到如下例所示的对?我想用LINQ代替for循环来形成这些,这可以完成同样的事情.由于延迟表达式树执行,使用LINQ可能会产生更高效的代码.
假设这是我的范围的例子:
D1 D2 D3 D4 D5 D6 D11 D12
|--------------| |------| |------| |------|
D7 D8
|--------------------------|
D9 D10
|-----------------------------------------------|
Run Code Online (Sandbox Code Playgroud)
获取不同日期的第一步将导致这些日期:
D1 D7 D2 D3 D4 D5 D6 D10 D11 D12
Run Code Online (Sandbox Code Playgroud)
D9和D8会掉线,因为它们是重复的.
下一步是形成对(我不知道如何使用LINQ执行此操作):
D1-D7, D7-D2, D2-D3, D3-D4, D4-D5, D5-D6, D6-D10, (D10-D11), D11-D12
Run Code Online (Sandbox Code Playgroud)
最后一步必须使用以下方法计算每对的日期:
D new = D from +(D to - D from)/ 2
应优选省略范围D 10 -D 11.但是如果省略它会导致代码过于复杂,那么可以通过单独的检查来保留和排除代码.但如果最初可以将其排除在外那么应该做什么.因此,如果您还提供有关如何形成排除空范围的对的信息,也欢迎您添加该信息.
你可以使用Zip():
var middleDates = dates.Zip(dates.Skip(1),
(a, b) => (a.AddTicks((b - a).Ticks / 2)))
.ToList();
Run Code Online (Sandbox Code Playgroud)
基于 @DavidB 的想法和 @AakashM 的原始答案的有趣想法,我提出了自己的解决方案,从一组日期中提取范围(同时也省略空范围)并计算范围中间日期。
如果您对此解决方案有任何改进建议或意见,热烈欢迎您发表评论。无论如何,这是我现在使用的最终代码(内联注释解释了其功能):
// counts range overlaps
int counter = 0;
// saves previous date to calculate midrange date
DateTime left = DateTime.Now;
// get mid range dates
IList<DateTime> dates = this.DateRanges
// select range starts and ends
.SelectMany(r => new[] {
new {
Date = r.From,
Counter = 1
},
new {
Date = r.To,
Counter = -1
}
})
// order dates because they come out mixed
.OrderBy(o => o.Date)
// convert dates to ranges; when non-empty & non-zero wide get mid date
.Select(o => {
// calculate middle date if range isn't empty and not zero wide
DateTime? result = null;
if ((counter != 0) && (left != o.Date))
{
result = o.Date.AddTicks(new DateTime((o.Date.Ticks - left.Ticks) / 2).Ticks);
}
// prepare for next date range
left = o.Date;
counter += o.Counter;
// return middle date when applicable otherwise null
return result;
})
// exclude empty and zero width ranges
.Where(d => d.HasValue)
// collect non nullable dates
.Select(d => d.Value)
.ToList();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2545 次 |
| 最近记录: |