我正在尝试选择一个列表的子组,其中项目具有连续的日期,例如
I'm trying to select a subgroup of a list where items have contiguous dates, e.g.
ID StaffID Title ActivityDate -- ------- ----------------- ------------ 1 41 Meeting with John 03/06/2010 2 41 Meeting with John 08/06/2010 3 41 Meeting Continues 09/06/2010 4 41 Meeting Continues 10/06/2010 5 41 Meeting with Kay 14/06/2010 6 41 Meeting Continues 15/06/2010我每次都使用一个枢轴点,因此将示例枢轴项设为3,我希望围绕枢轴获得以下结果连续事件:
I'm using a pivot point each time, so take the example pivot item as 3, I'd like to get the following resulting contiguous events around the pivot:
ID StaffID Title ActivityDate -- ------- ----------------- ------------ 2 41 Meeting with John 08/06/2010 3 41 Meeting Continues 09/06/2010 4 41 Meeting Continues 10/06/2010我当前的实现方式是费力地走"过去,然后走到未来,以建立列表:
My current implementation is a laborious "walk" into the past, then into the future, to build the list:
var activity = // item number 3: Meeting Continues (09/06/2010) var orderedEvents = activities.OrderBy(a => a.ActivityDate).ToArray(); // Walk into the past until a gap is found var preceedingEvents = orderedEvents.TakeWhile(a => a.ID != activity.ID); DateTime dayBefore; var previousEvent = activity; while (previousEvent != null) { dayBefore = previousEvent.ActivityDate.AddDays(-1).Date; previousEvent = preceedingEvents.TakeWhile(a => a.ID != previousEvent.ID).LastOrDefault(); if (previousEvent != null) { if (previousEvent.ActivityDate.Date == dayBefore) relatedActivities.Insert(0, previousEvent); else previousEvent = null; } } // Walk into the future until a gap is found var followingEvents = orderedEvents.SkipWhile(a => a.ID != activity.ID); DateTime dayAfter; var nextEvent = activity; while (nextEvent != null) { dayAfter = nextEvent.ActivityDate.AddDays(1).Date; nextEvent = followingEvents.SkipWhile(a => a.ID != nextEvent.ID).Skip(1).FirstOrDefault(); if (nextEvent != null) { if (nextEvent.ActivityDate.Date == dayAfter) relatedActivities.Add(nextEvent); else nextEvent = null; } }列表relatedActivities然后应按顺序包含连续事件.
The list relatedActivities should then contain the contiguous events, in order.
是否有更好的方法(也许使用LINQ)?
我想到了使用 .Aggregate() ,但是当它在序列中发现缺口时,却想不出如何使聚合爆发.
I had an idea of using .Aggregate() but couldn't think how to get the aggregate to break out when it finds a gap in the sequence.
推荐答案在这种情况下,我认为标准的foreach循环可能比LINQ查询更具可读性:
In this case I think that a standard foreach loop is probably more readable than a LINQ query:
var relatedActivities = new List<TActivity>(); bool found = false; foreach (var item in activities.OrderBy(a => a.ActivityDate)) { int count = relatedActivities.Count; if ((count > 0) && (relatedActivities[count - 1].ActivityDate.Date.AddDays(1) != item.ActivityDate.Date)) { if (found) break; relatedActivities.Clear(); } relatedActivities.Add(item); if (item.ID == activity.ID) found = true; } if (!found) relatedActivities.Clear();对于它的价值,这是一个大致等效的LINQ查询,而且可读性差得多:
For what it's worth, here's a roughly equivalent -- and far less readable -- LINQ query:
var relatedActivities = activities .OrderBy(x => x.ActivityDate) .Aggregate ( new { List = new List<TActivity>(), Found = false, ShortCircuit = false }, (a, x) => { if (a.ShortCircuit) return a; int count = a.List.Count; if ((count > 0) && (a.List[count - 1].ActivityDate.Date.AddDays(1) != x.ActivityDate.Date)) { if (a.Found) return new { a.List, a.Found, ShortCircuit = true }; a.List.Clear(); } a.List.Add(x); return new { a.List, Found = a.Found || (x.ID == activity.ID), a.ShortCircuit }; }, a => a.Found ? a.List : new List<TActivity>() );更多推荐
使用LINQ按日期对序列进行分组,没有间隔
发布评论