Linq group by DateTime.Date然后再由另一个标准组成

时间:2014-04-17 11:59:58

标签: c# linq group-by

我有一个IEnumerable<Bar>,其中Bar包含DateTime类型变量TimeStamp和其他数据。

我有以下代码,

var convertedBars = from myData in bars
                    group myData by (int) myData.TimeStamp.TimeOfDay.TotalMinutes / 60 into barData
                    select new Bar(){
                        TimeStamp = barData.FirstOrDefault().TimeStamp,
                        Open = barData.FirstOrDefault().Open,
                        Low = barData.Min(bd => bd.Low),
                        High = barData.Max(bd => bd.High),
                        Close = barData.LastOrDefault().Close,
                    };

返回IEnumerable<Bar>,其中条形被分组为60分钟的条形图。只要原始bars集合包含仅有一个和同一天时间戳的条形图,这就可以正常工作。如果源集合包含多天,则所有条形图被分组为最多24个小时的桶。

如何调整代码,以便首先按Date对分组进行分组,然后按TotalMinutes /60分组(如上所述),以便每个日期分别使用60分钟的分组?

编辑

我在某种程度上概括了查询,有人可以评论这是正确的方法还是我错过了一些明显的东西?

var requestedTimeSpan = TimeSpan.FromHours(1); //1 hour
long numberTicks = requestedTimeSpan.Ticks;
var convertedBars = from myData in bars
                    group myData by myData.TimeStamp.Ticks / numberTicks  into barData
                    select new Bar()
                    {
                        TimeStamp = new DateTime(barData.Key * numberTicks),
                        Open = barData.First().Open,
                        Low = barData.Min(bd => bd.Low),
                        High = barData.Max(bd => bd.High),
                        Close = barData.Last().Close,
                    };

2 个答案:

答案 0 :(得分:2)

尝试使用anonymous type进行分组:

group myData by new { myData.TimeStamp.Date,
       Hour = (int) myData.TimeStamp.TimeOfDay.TotalMinutes / 60 } into barData

答案 1 :(得分:0)

尝试类似:

var convertedBars =
        bars.GroupBy(b => b.TimeStamp.Date).Select(g => g.GroupBy(b2 => (int)(b2.TimeStamp.TimeOfDay.TotalMinutes / 60))).Select(gb => new Bar()
        {                
            TimeStamp = gb.FirstOrDefault().FirstOrDefault().TimeStamp,
            Open = gb.FirstOrDefault().FirstOrDefault().Open,
            Low = gb.SelectMany(bd => bd).Min(ibd => ibd.Low),
            High = gb.SelectMany(bd => bd).Max(ibd => ibd.High),
            Close = gb.LastOrDefault().LastOrDefault().Close,
        });