LINQ Group通过连续时间

编程入门 行业动态 更新时间:2024-10-28 16:24:06
本文介绍了LINQ Group通过连续时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

假设我有一个简单的结构,如下所示:

Assuming I have a simple structure that looks like this:

public class Range { public DateTime Start { get; set; } public DateTime End { get; set; } public Range(DateTime start, DateTime end) { this.Start = start; this.End = end; } }

然后我像这样创建一个集合:

And I create an collection like so:

var dr1 = new Range(new DateTime(2011, 11, 1, 12, 0, 0), new DateTime(2011, 11, 1, 13, 0, 0)); var dr2 = new Range(new DateTime(2011, 11, 1, 13, 0, 0), new DateTime(2011, 11, 1, 14, 0, 0)); var dr3 = new Range(new DateTime(2011, 11, 1, 14, 0, 0), new DateTime(2011, 11, 1, 15, 0, 0)); var dr4 = new Range(new DateTime(2011, 11, 1, 16, 0, 0), new DateTime(2011, 11, 1, 17, 0, 0)); var ranges = new List<Range>() { dr1, dr2, dr3, dr4 };

我要对连续的范围进行分组-即,如果前一个范围的结束"值与下一个范围的开始"值相同,则它们是连续的.

What I want to do is group the ranges where they are continuous - i.e. they are continuous if the End value of the previous Range is the same as the Start of the next.

我们可以假设Range值中没有冲突/重复或重叠.

We can assume that there are no collisions/duplicates or overlaps in the Range values.

在发布的示例中,我将分为两组:

In the example posted, I would end up with two groups:

2011-11-1 12:00:00 - 2011-11-1 15:00:00 2011-11-1 16:00:00 - 2011-11-1 17:00:00

为此很容易找到一个迭代解决方案.但是,有没有什么我可以使用LINQ魔术贴来实现的呢?

It's fairly easy to come up with an iterative solution for this. But is there some LINQ magic I can use to get this in a pretty one-liner?

推荐答案

您最好的选择是使用 yield 和扩展方法:

Your best bet is to use yield and an extension method:

static IEnumerable<Range> GroupContinuous(this IEnumerable<Range> ranges) { // Validate parameters. // Can order by start date, no overlaps, no collisions ranges = ranges.OrderBy(r => r.Start); // Get the enumerator. using (IEnumerator<Range> enumerator = ranges.GetEnumerator(); { // Move to the first item, if nothing, break. if (!enumerator.MoveNext()) yield break; // Set the previous range. Range previous = enumerator.Current; // Cycle while there are more items. while (enumerator.MoveNext()) { // Get the current item. Range current = enumerator.Current; // If the start date is equal to the end date // then merge with the previous and continue. if (current.Start == previous.End) { // Merge. previous = new Range(previous.Start, current.End); // Continue. continue; } // Yield the previous item. yield return previous; // The previous item is the current item. previous = current; } // Yield the previous item. yield return previous; } }

已授予,对 OrderBy 的调用导致ranges序列的完整迭代,但是无法避免.订购完成后,您可以避免在返回结果之前将其具体化.只要条件允许,您只需yield结果.

Granted, the call to OrderBy is going to cause a full iteration of the ranges sequence, but there's no avoiding that. Once you have it ordered, you can prevent having to materialize your results before returning them; you simply yield the results if the conditions dictate.

但是,如果您知道序列是有序的,则根本不必调用OrderBy,并且在遍历列表并在不同的折叠的Range实例上断开时可以yield个项目.

If you know that the sequence is ordered, however, then you don't have to call OrderBy at all, and you can yield items as you traverse the list and break on different collapsed Range instances.

最终,如果序列是无序的,那么您有两个选择:

Ultimately, if the sequence is unordered, then you have two options:

  • 对列表进行排序,然后进行处理(请记住,OrderBy也被推迟,但是必须使用一个完整的迭代来对序列进行排序),如果需要处理,则使用yield返回该项目
  • 立即处理整个序列,然后作为完整的物化序列返回
  • Order the list and then process (remember, OrderBy is deferred as well, but will have to use one full iteration to order the sequence), using yield to return the item when you have one to process
  • Process the entire sequence at once and return as an entire materialized sequence

更多推荐

LINQ Group通过连续时间

本文发布于:2023-10-18 03:00:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1502879.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:时间   LINQ   Group

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!