用纯 LINQ 完全解决这个问题实际上是相当困难的。为了让生活更轻松,您需要编写至少一个帮助方法来允许您转换枚举。看看下面的例子。在这里,我使用了一个IEnumerableofTimeInterval并有一个自定义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返回 a 的自定义方法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 天。