C#从linq组中的日期获取分钟数
C# get minute number from date in linq group by
我需要按一天中的每一分钟对我的数据进行分组,并获取在那一分钟内发生的事件的计数。我目前有:
items.GroupBy(x => new
{
x.date.Minute,
x.date.Hour
})
.Select(x => new TransferObject
{
Minute = x.Key.Minute,
Hour = x.Key.Hour,
Count = x.Count(),
Day = date
}).OrderBy(x => x.Hour).ThenBy(x => x.Minute).ToList();
这满足了我的需要,但问题是我可能没有每一分钟的数据点,如果我没有那一分钟的数据,我如何向 Count
字段添加 0?或者我可以添加分钟数 (0...1440) 并稍后添加缺失值。
编辑
解决方案目前仅按开始日期分组,但该对象实际上有一个字段 end_date
。所以基本上现在我有在那一分钟开始的所有事件,但我需要得到那一分钟 运行 的事件数。
我拥有的数据包含:
date end_date
2015-05-15 09:52:15.650 2015-05-15 09:55:38.097
2015-05-15 09:52:15.633 2015-05-15 09:52:16.097
2015-05-15 09:52:11.633 2015-05-15 09:52:13.047
2015-05-15 09:51:49.097 2015-05-15 09:55:17.687
2015-05-15 09:51:49.087 2015-05-15 09:56:17.510
目前它不使用 end_date
字段所以输出是
{Count:2;Hour:9;Minute:51}
{Count:3;Hour:9;Minute:52}
我需要所有 运行 的事件,比如
{Count:2;Hour:9;Minute:51}
{Count:5;Hour:9;Minute:52}
{Count:3;Hour:9;Minute:53}
{Count:3;Hour:9;Minute:54}
{Count:3;Hour:9;Minute:55}
{Count:2;Hour:9;Minute:56}
看来,您想要 GroupJoin()
而不仅仅是 GroupBy()
,类似这样的东西:
var source = ... // Your query;
var result = Enumerable
.Range(0, 1440) // All the minutes that should be in the result
.GroupJoin(source,
minutes => minutes,
item => item.Hour * 60 + item.Minute,
(minutes, items) => new {
hour = minutes / 60,
minute = minutes % 60,
count = items.Count() } ); // Count() can well return 0...
这应该可以在没有任何 join
的情况下工作。假设项目中只有一个日期。
var date = items.Select(i => i.date).Min();
Enumerable.Range(0, 60 * 24)
.Select(i =>
new
{
Minute = i % 60,
Hour = i / 60,
Day = date,
Count = items.Where(j => j.date.Hour = i / 60 && j.date.Minute = i % 60).Count()
});
首先,您可以使用一些简单的 LINQ 生成一天中的所有小时和分钟:
var all = Enumerable.Range(0,24)
.SelectMany(x => Enumerable.Range(0,60),
(x,y) => new {Hr = x, Min=y});
foreach(var a in all)
Console.WriteLine("{0}:{1}",a.Hr,a.Min); // 00:00 thru 23:59
实例:http://rextester.com/NPNKN82691
然后您可以使用此集合加入您的原始结果以形成最终输出:
var all = Enumerable.Range(0,24)
.SelectMany(x => Enumerable.Range(0,60),
(x,y) => new {Hr = x, Min=y});
var items = new[]{
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,3,0)}
};
var results = all.GroupJoin(items,
x => new {Hour = x.Hr,Minute = x.Min},
y => new {Hour = y.Date.Hour,Minute = y.Date.Minute},
(x,y) => new {Hour = x.Hr, Minute = x.Min, Count = y.Count()});
foreach(var result in results)
Console.WriteLine("{0:00}:{1:00} = {2}",result.Hour, result.Minute, result.Count);
输出
00:00 = 0
00:01 = 6
00:02 = 0
00:03 = 1
00:04 = 0
//..snip..//
23:55 = 0
23:56 = 0
23:57 = 0
23:58 = 0
23:59 = 0
实例http://rextester.com/OAYZ95244
编辑
考虑到您考虑 范围 日期的要求更改,您可以添加一个新的 class 和用于从每个项目推断小时和分钟的方法:
// classes used
public class ExtrapolatedItem
{
public int Hour{get;set;}
public int Minute{get;set;}
}
public class Item{
public DateTime Date{get;set;}
public DateTime EndDate{get;set;}
}
// method
private static IEnumerable<ExtrapolatedItem> Extrapolate(Item item)
{
for(var d = item.Date;d<=item.EndDate; d = d.AddMinutes(1))
{
yield return new ExtrapolatedItem{ Hour = d.Hour, Minute = d.Minute};
}
}
然后可以像这样在原始方法中使用:
var items = new[]{
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,3,0),EndDate = new DateTime(2015,1,1,0,5,0)}
};
var results = all.GroupJoin(items.SelectMany(Extrapolate), // extrapolate each item to a list of extrapolated items
x => new {Hour = x.Hr,Minute = x.Min},
y => new {Hour = y.Hour,Minute = y.Minute},
(x,y) => new {Hour = x.Hr, Minute = x.Min, Count = y.Count()});
输出
00:00 = 0
00:01 = 6
00:02 = 6
00:03 = 7
00:04 = 7
00:05 = 7
00:06 = 0
00:07 = 0
//..snip..//
我需要按一天中的每一分钟对我的数据进行分组,并获取在那一分钟内发生的事件的计数。我目前有:
items.GroupBy(x => new
{
x.date.Minute,
x.date.Hour
})
.Select(x => new TransferObject
{
Minute = x.Key.Minute,
Hour = x.Key.Hour,
Count = x.Count(),
Day = date
}).OrderBy(x => x.Hour).ThenBy(x => x.Minute).ToList();
这满足了我的需要,但问题是我可能没有每一分钟的数据点,如果我没有那一分钟的数据,我如何向 Count
字段添加 0?或者我可以添加分钟数 (0...1440) 并稍后添加缺失值。
编辑
解决方案目前仅按开始日期分组,但该对象实际上有一个字段 end_date
。所以基本上现在我有在那一分钟开始的所有事件,但我需要得到那一分钟 运行 的事件数。
我拥有的数据包含:
date end_date
2015-05-15 09:52:15.650 2015-05-15 09:55:38.097
2015-05-15 09:52:15.633 2015-05-15 09:52:16.097
2015-05-15 09:52:11.633 2015-05-15 09:52:13.047
2015-05-15 09:51:49.097 2015-05-15 09:55:17.687
2015-05-15 09:51:49.087 2015-05-15 09:56:17.510
目前它不使用 end_date
字段所以输出是
{Count:2;Hour:9;Minute:51}
{Count:3;Hour:9;Minute:52}
我需要所有 运行 的事件,比如
{Count:2;Hour:9;Minute:51}
{Count:5;Hour:9;Minute:52}
{Count:3;Hour:9;Minute:53}
{Count:3;Hour:9;Minute:54}
{Count:3;Hour:9;Minute:55}
{Count:2;Hour:9;Minute:56}
看来,您想要 GroupJoin()
而不仅仅是 GroupBy()
,类似这样的东西:
var source = ... // Your query;
var result = Enumerable
.Range(0, 1440) // All the minutes that should be in the result
.GroupJoin(source,
minutes => minutes,
item => item.Hour * 60 + item.Minute,
(minutes, items) => new {
hour = minutes / 60,
minute = minutes % 60,
count = items.Count() } ); // Count() can well return 0...
这应该可以在没有任何 join
的情况下工作。假设项目中只有一个日期。
var date = items.Select(i => i.date).Min();
Enumerable.Range(0, 60 * 24)
.Select(i =>
new
{
Minute = i % 60,
Hour = i / 60,
Day = date,
Count = items.Where(j => j.date.Hour = i / 60 && j.date.Minute = i % 60).Count()
});
首先,您可以使用一些简单的 LINQ 生成一天中的所有小时和分钟:
var all = Enumerable.Range(0,24)
.SelectMany(x => Enumerable.Range(0,60),
(x,y) => new {Hr = x, Min=y});
foreach(var a in all)
Console.WriteLine("{0}:{1}",a.Hr,a.Min); // 00:00 thru 23:59
实例:http://rextester.com/NPNKN82691
然后您可以使用此集合加入您的原始结果以形成最终输出:
var all = Enumerable.Range(0,24)
.SelectMany(x => Enumerable.Range(0,60),
(x,y) => new {Hr = x, Min=y});
var items = new[]{
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0)},
new Item{Date = new DateTime(2015,01,01,0,3,0)}
};
var results = all.GroupJoin(items,
x => new {Hour = x.Hr,Minute = x.Min},
y => new {Hour = y.Date.Hour,Minute = y.Date.Minute},
(x,y) => new {Hour = x.Hr, Minute = x.Min, Count = y.Count()});
foreach(var result in results)
Console.WriteLine("{0:00}:{1:00} = {2}",result.Hour, result.Minute, result.Count);
输出
00:00 = 0
00:01 = 6
00:02 = 0
00:03 = 1
00:04 = 0
//..snip..//
23:55 = 0
23:56 = 0
23:57 = 0
23:58 = 0
23:59 = 0
实例http://rextester.com/OAYZ95244
编辑
考虑到您考虑 范围 日期的要求更改,您可以添加一个新的 class 和用于从每个项目推断小时和分钟的方法:
// classes used
public class ExtrapolatedItem
{
public int Hour{get;set;}
public int Minute{get;set;}
}
public class Item{
public DateTime Date{get;set;}
public DateTime EndDate{get;set;}
}
// method
private static IEnumerable<ExtrapolatedItem> Extrapolate(Item item)
{
for(var d = item.Date;d<=item.EndDate; d = d.AddMinutes(1))
{
yield return new ExtrapolatedItem{ Hour = d.Hour, Minute = d.Minute};
}
}
然后可以像这样在原始方法中使用:
var items = new[]{
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,1,0),EndDate = new DateTime(2015,1,1,0,5,0)},
new Item{Date = new DateTime(2015,01,01,0,3,0),EndDate = new DateTime(2015,1,1,0,5,0)}
};
var results = all.GroupJoin(items.SelectMany(Extrapolate), // extrapolate each item to a list of extrapolated items
x => new {Hour = x.Hr,Minute = x.Min},
y => new {Hour = y.Hour,Minute = y.Minute},
(x,y) => new {Hour = x.Hr, Minute = x.Min, Count = y.Count()});
输出
00:00 = 0
00:01 = 6
00:02 = 6
00:03 = 7
00:04 = 7
00:05 = 7
00:06 = 0
00:07 = 0
//..snip..//