我有一个事件列表,现在我想找出哪些事件重叠.您可以在下面找到我目前拥有的代码,但我遇到的问题是,搜索到的项目也包含在列表中.
List<SomeEventObject> overlappingEvents = new List<SomeEventObject>();
foreach (SomeEventObject eventItem in EventList)
{
bool overlapping = false;
foreach (SomeEventObject anotherEventItem in EventList)
{
if (eventItem.StartDate <= anotherEventItem.EndDate &&
eventItem.EndDate >= anotherEventItem.StartDate)
{
overlapping = true;
overlappingEvents.Add(anotherEventItem);
}
}
if (overlapping)
overlappingEvents.Add(eventItem);
}
Run Code Online (Sandbox Code Playgroud)
我需要创建一个没有搜索项目的新列表.因此我问是否有一个很好的LINQ表达式可以为我处理.这是我想到的一些伪代码:
EventList.Where(e =>
eventItem.StartDate <= e.EndDate &&
eventItem.EndDate >= e.StartDate);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,eventItem当然不存在.
结果我认为我需要两个列表:一个具有重叠事件,一个具有非重叠事件.但.Except()如果我有重叠的事件列表,这应该是可能的.
编辑:
我创建了一个dotnetfiddle,以便人们可以玩它.一个重要的问题是重叠算法.
活动1:
StartDate:今天,10
:00 EndDate:今天,10:05
事件2:
StartDate:今天,10
:05 EndDate:今天,10:10
如果您向用户提供此信息,则不会重叠.所以我要修改我的算法.
我会这样做:
var overlappingEvents =
(
from e1 in EventList
from e2 in EventList
where e1 != e2
where e1.StartDate <= e2.EndDate
where e1.EndDate >= e2.StartDate
from e in new [] { e1, e2 }
select e
).ToList();
Run Code Online (Sandbox Code Playgroud)
我认为这应该很简单。
根据评论,这个版本只返回一个EventList元素一次,不管它参与了多少重叠。
var overlappingEvents =
(
from e1 in EventList
where EventList
.Where(e2 => e1 != e2)
.Where(e2 => e1.StartDate <= e2.EndDate)
.Where(e2 => e1.EndDate >= e2.StartDate)
.Any()
select e1
).ToList();
Run Code Online (Sandbox Code Playgroud)
也可以写成:
var overlappingEvents =
EventList
.Where(e1 =>
EventList
.Where(e2 => e1 != e2)
.Where(e2 => e1.StartDate <= e2.EndDate)
.Where(e2 => e1.EndDate >= e2.StartDate)
.Any())
.ToList();
Run Code Online (Sandbox Code Playgroud)
根据进一步的评论,这里是如何配对事件:
var overlappingEvents =
(
from e1 in EventList
from e2 in EventList
where e1 != e2
where e1.StartDate <= e2.EndDate
where e1.EndDate >= e2.StartDate
select new [] { e1, e2 }
).ToList();
Run Code Online (Sandbox Code Playgroud)
现在overlappingEvents是一个数组列表 -List<SomeEventObject[]>而不是List<SomeEventObject>. 该数组包含重叠事件。
我会尝试这样的事情:
var searchedFor = EventList.First(); // Replace by the proper one
var overlapping = EventList.Where(e => e != searchedFor &&
EventList.Any(ev => e != ev && ev.StartDate <= e.EndDate && ev.EndDate >= e.StartDate))
// Alternatively with Except
var overlapping = EventList.Except(new[] { searchFor }).Where(e =>
EventList.Any(ev => e != ev && ev.StartDate <= e.EndDate && ev.EndDate >= e.StartDate))
Run Code Online (Sandbox Code Playgroud)
对于非重叠,您只需EventList使用以下方法过滤重叠事件Except:
var nonOverlapping = EventList.Except(overlappingEvents);
Run Code Online (Sandbox Code Playgroud)
我不知道你的情况SomeEventObject,但你可能需要通过一些比较来改变不平等比较Id。
有一个关于检测 C# 中重叠周期的非常好的问答,您可能想研究一下。为了方便起见,您还可以按如下方式分解支票:
Func<SomeEventObject, SomeEventObject, bool> areOverlapped = (e1, e2) =>
e1.StartDate <= e2.EndDate && e1.EndDate >= e2.StartDate;
var overlapping = EventList.Where(e => e != searchedFor &&
EventList.Any(ev => e != ev && areOverlapped(e, ev)));
Run Code Online (Sandbox Code Playgroud)