C# LINQ:按时间分组的事件
此代码查找一起发生的事件组。 它们之间的间隔最长为5秒。两组之间的时间超过5秒 更新:组是日期时间列表。一个组包含的日期时间间隔小于5秒。发生时间超过5秒的DateTimes将放置到下一组C# LINQ:按时间分组的事件,c#,linq,grouping,C#,Linq,Grouping,此代码查找一起发生的事件组。 它们之间的间隔最长为5秒。两组之间的时间超过5秒 更新:组是日期时间列表。一个组包含的日期时间间隔小于5秒。发生时间超过5秒的DateTimes将放置到下一组 public static List<List<DateTime>> GetGroups(int count) { var groups = new List<List<DateTime>>(); groups.Add(new List<DateT
public static List<List<DateTime>> GetGroups(int count)
{
var groups = new List<List<DateTime>>();
groups.Add(new List<DateTime>());
using (var db = new DbContainer())
{
foreach (var row in db.Table)
{
if (!groups.Last().Any() || (groups.Last().Any() && (row.Time - groups.Last().Last()).TotalSeconds <= 5))
{
groups.Last().Add(row.Time);
}
else if (groups.Count < count)
{
groups.Add(new List<DateTime>());
groups.Last().Add(row.Time);
continue;
}
if (groups.Count == count)
{
break;
}
}
}
return groups;
}
公共静态列表GetGroups(int计数)
{
变量组=新列表();
添加(新列表());
使用(var db=new DbContainer())
{
foreach(数据库表中的变量行)
{
如果(!groups.Last().Any()| |(groups.Last().Any()&&(row.Time-groups.Last().Last()).TotalSeconds从本质上讲,使用标准LINQ to Objects操作符很难表达的查询中唯一棘手的部分是根据连续项之间的距离对项进行分组
仅此一点,我将使用迭代器块:
// Needs argument-checking, but you'll need another method to do it eagerly.
public static IEnumerable<List<T>> GroupByConsective<T>
(this IEnumerable<T> source, Func<T, T, bool> prevNextPredicate)
{
var currentGroup = new List<T>();
foreach (var item in source)
{
if (!currentGroup.Any() || prevNextPredicate(currentGroup.Last(), item))
currentGroup.Add(item); // Append: empty group or nearby elements.
else
{
// The group is done: yield it out
// and create a fresh group with the item.
yield return currentGroup;
currentGroup = new List<T> { item };
}
}
// If the group still has items once the source is fully consumed,
// we need to yield it out.
if(currentGroup.Any())
yield return currentGroup;
}
//需要参数检查,但您需要另一种方法来急切地进行检查。
公共静态IEnumerable groupByConcertive
(此IEnumerable源,Func prevenxtpredicate)
{
var currentGroup=新列表();
foreach(源中的var项)
{
如果(!currentGroup.Any()| | prevenxtpredicate(currentGroup.Last(),item))
currentGroup.Add(item);//追加:空组或附近的元素。
其他的
{
//小组完成了:放弃它
//并使用该项创建一个新组。
收益率返回电流组;
currentGroup=新列表{item};
}
}
//如果资源完全消耗后,该组仍有项目,
//我们需要放弃它。
if(currentGroup.Any())
收益率返回电流组;
}
对于其他一切(投影、限制组数、物化为集合),标准LINQ to对象都可以正常工作。因此,您的查询变成:
using (var db = new DbContainer())
{
var groups = db.Table
.Select(row => row.Time)
.GroupByConsecutive((prev, next) => next.Subtract(prev)
.TotalSeconds <= 5)
.Take(count)
.ToList();
// Use groups...
}
使用(var db=new DbContainer())
{
var groups=db.Table
.Select(行=>row.Time)
.GroupByContinuous((上一个,下一个)=>下一个。减去(上一个)
.TotalSeconds本质上,使用标准LINQ to Objects操作符很难表达的查询中唯一棘手的部分是根据连续项之间的距离对项进行分组
仅此一点,我将使用迭代器块:
// Needs argument-checking, but you'll need another method to do it eagerly.
public static IEnumerable<List<T>> GroupByConsective<T>
(this IEnumerable<T> source, Func<T, T, bool> prevNextPredicate)
{
var currentGroup = new List<T>();
foreach (var item in source)
{
if (!currentGroup.Any() || prevNextPredicate(currentGroup.Last(), item))
currentGroup.Add(item); // Append: empty group or nearby elements.
else
{
// The group is done: yield it out
// and create a fresh group with the item.
yield return currentGroup;
currentGroup = new List<T> { item };
}
}
// If the group still has items once the source is fully consumed,
// we need to yield it out.
if(currentGroup.Any())
yield return currentGroup;
}
//需要参数检查,但您需要另一种方法来急切地进行检查。
公共静态IEnumerable groupByConcertive
(此IEnumerable源,Func prevenxtpredicate)
{
var currentGroup=新列表();
foreach(源中的var项)
{
如果(!currentGroup.Any()| | prevenxtpredicate(currentGroup.Last(),item))
currentGroup.Add(item);//追加:空组或附近的元素。
其他的
{
//小组完成了:放弃它
//并使用该项创建一个新组。
收益率返回电流组;
currentGroup=新列表{item};
}
}
//如果资源完全消耗后,该组仍有项目,
//我们需要放弃它。
if(currentGroup.Any())
收益率返回电流组;
}
对于其他一切(投影、限制组数、物化为集合),标准LINQ to对象都可以正常工作。因此,您的查询变成:
using (var db = new DbContainer())
{
var groups = db.Table
.Select(row => row.Time)
.GroupByConsecutive((prev, next) => next.Subtract(prev)
.TotalSeconds <= 5)
.Take(count)
.ToList();
// Use groups...
}
使用(var db=new DbContainer())
{
var groups=db.Table
.Select(行=>row.Time)
.GroupByContinuous((上一个,下一个)=>下一个。减去(上一个)
.总秒数
使用datetime.ToString(),格式为每秒gen number,然后每5秒使用/5
编辑:
我不太确定你在看什么,但我试过了,效果很好
var now = DateTime.Now;
Console.WriteLine(now.ToString("yyyyMMddHHmmss"));
Enumerable.Range(0, 57)
.Select(offset => now.AddSeconds(offset))
.GroupBy(interval => long.Parse(interval.ToString("yyyyMMddHHmmss")) / 5)
.ToList()
.ForEach(g => Console.WriteLine("{0}: {1} - {2}", g.Count(), g.Min().ToString("yyyyMMddHHmmss"), g.Max().ToString("yyyyMMddHHmmss")));
Console.ReadKey();
下面是示例输出
20120125144606
4: 20120125144606 - 20120125144609
5: 20120125144610 - 20120125144614
5: 20120125144615 - 20120125144619
5: 20120125144620 - 20120125144624
5: 20120125144625 - 20120125144629
5: 20120125144630 - 20120125144634
5: 20120125144635 - 20120125144639
5: 20120125144640 - 20120125144644
5: 20120125144645 - 20120125144649
5: 20120125144650 - 20120125144654
5: 20120125144655 - 20120125144659
3: 20120125144700 - 20120125144702
示例日期时间以5秒的间隔分组。例如10-14秒。如果您想要11-15秒,可以在设备前加1秒
:)
使用datetime.ToString(),格式为每秒gen number,然后每5秒使用/5
编辑:
我不太确定你在看什么,但我试过了,效果很好
var now = DateTime.Now;
Console.WriteLine(now.ToString("yyyyMMddHHmmss"));
Enumerable.Range(0, 57)
.Select(offset => now.AddSeconds(offset))
.GroupBy(interval => long.Parse(interval.ToString("yyyyMMddHHmmss")) / 5)
.ToList()
.ForEach(g => Console.WriteLine("{0}: {1} - {2}", g.Count(), g.Min().ToString("yyyyMMddHHmmss"), g.Max().ToString("yyyyMMddHHmmss")));
Console.ReadKey();
下面是示例输出
20120125144606
4: 20120125144606 - 20120125144609
5: 20120125144610 - 20120125144614
5: 20120125144615 - 20120125144619
5: 20120125144620 - 20120125144624
5: 20120125144625 - 20120125144629
5: 20120125144630 - 20120125144634
5: 20120125144635 - 20120125144639
5: 20120125144640 - 20120125144644
5: 20120125144645 - 20120125144649
5: 20120125144650 - 20120125144654
5: 20120125144655 - 20120125144659
3: 20120125144700 - 20120125144702
示例日期时间以5秒的间隔分组。例如10-14秒。如果您想要11-15秒,可以在设备前加1秒
:)看起来代码无法编译。@M.Babcock-groups.Add(new List());
@ChaosPandion-是的,我修好了it@scazy-所以您试图将不起作用的代码转换为LINQ?@M.Babcock-只是我试图防止break
语句出现奇怪的超时异常。看起来该代码无法编译。@M.Babcock-groups.Add(new List());
@ChaosPandion-是的,我修好了it@scazy-所以你正在尝试将不工作的代码转换为LINQ?@M.Babcock-我只是在尝试防止break
语句出现奇怪的超时异常。看起来很漂亮…工作正常…序列通用。谢谢。看起来很漂亮…工作正常…序列通用是的。谢谢。除以五对我的情况不正确。EF4不支持long.Parse
。除以五对我的情况不正确。EF4不支持long.Parse
。