实际上很难完全用纯LINQ来解决这个问题。为了使生活更轻松,您需要编写至少一个帮助器方法,该方法允许您转换枚举。看看下面的例子。在这里,我使用TimeInterval
一个IEnumerable
的和有一个自定义Split
方法(用C#迭代器实现的),在一个Tuple
联接两个元件一起:
class TimeInterval
{
DateTime Start;
DateTime End;
int Value;
}
IEnumerable<TimeInterval> ToHourlyIntervals(
IEnunumerable<TimeInterval> halfHourlyIntervals)
{
return
from pair in Split(halfHourlyIntervals)
select new TimeInterval
{
Start = pair.Item1.Start,
End = pair.Item2.End,
Value = pair.Item1.Value + pair.Item2.Value
};
}
static IEnumerable<Tuple<T, T>> Split<T>(
IEnumerable<T> source)
{
using (var enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
T first = enumerator.Current;
if (enumerator.MoveNext())
{
T second = enumerator.Current;
yield return Tuple.Create(first, second);
}
}
}
}
同样可以适用于该问题的第一部分(从字符串列表)中提取每半小时TimeInterval
S:
IEnumerable<TimeInterval> ToHalfHourlyIntervals(
IEnumerable<string> inputLines)
{
return
from triple in TripleSplit(inputLines)
select new TimeInterval
{
Start = DateTime.Parse(triple.Item1.Replace("Start: ", "")),
End = DateTime.Parse(triple.Item2.Replace("End: ", "")),
Value = Int32.Parse(triple.Item3)
};
}
这里我使用一个自定义的TripleSplit
方法返回的Tuple<T, T, T>
(这将是容易写)。有了这个,完整的解决方案看起来像这样:
// Read data lazilzy from disk (or any other source)
var lines = File.ReadLines(path);
var halfHourlyIntervals = ToHalfHourlyIntervals(lines);
var hourlyIntervals = ToHourlyIntervals(halfHourlyIntervals);
foreach (var interval in hourlyIntervals)
{
// process
}
这个解决方案的好处是它完全延迟。这一次处理一行,它允许您处理无限期地大源没有任何内存不足的例外,这似乎是重要的危险考虑您给出的要求:
这一数据不断去了一个星期,然后30天和365天。
我在第二个例子中注意到,该值为2.您是否改变了最终值和添加下一个的当前值? –
你的例子给出了每次30分钟的差距。那是对的吗? 'End'总是'**:30'和'Start'总是'**:00' – hwcverwe
我不同意闭幕者关闭这个问题,因为它太过本地化。问题是关于解析几种类型的项目的结构集合,这给了其他访问者非常有趣。但是,这个问题实际上表达得很差,这将是一个很好的理由。 – Steven