如何使用 LINQ 知道周期集合中是否存在重叠

发布于 2024-10-28 21:44:01 字数 840 浏览 0 评论 0原文

我有一个时期[FromDate, ToDate]的集合。

我想知道给定的时期和集合中的时期之间是否有重叠。

我已经开始了:

 // periodToCheck is the given item
 bool conflict = Periods.Any(p => ((p.FromDate >= periodToCheck.fromDate && 
                                    p.FromDate <= periodToCheck.toDate)
                                  ||
                                   (p.ToDate >= periodToCheck.fromDate && 
                                    p.ToDate <= periodToCheck.toDate))
                             );

它没有涵盖所有情况的问题,例如:

[2010.1.1], [2010.1.31]
[2010.1.5], [2010.1.6] // Is valid in the query in spite of it is not valid 
                       // (because there is intersection).

如果我讨论更多情况,我认为查询会变得更加复杂。

我想知道你是否可以用最简单有效的方法帮助我。

问候。

I have a collection of periods [FromDate, ToDate].

I would know whether there is any overlap between a given period and the periods in the collection.

I've already started with this:

 // periodToCheck is the given item
 bool conflict = Periods.Any(p => ((p.FromDate >= periodToCheck.fromDate && 
                                    p.FromDate <= periodToCheck.toDate)
                                  ||
                                   (p.ToDate >= periodToCheck.fromDate && 
                                    p.ToDate <= periodToCheck.toDate))
                             );

The problem that it does not cover all the situation, for example:

[2010.1.1], [2010.1.31]
[2010.1.5], [2010.1.6] // Is valid in the query in spite of it is not valid 
                       // (because there is intersection).

And if I discuss more situation I think the query will become more complicated.

I wonder if you could help me with the simplest valid way.

Regards.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

Hello爱情风 2024-11-04 21:44:01

相反,可以这样处理:如果检查日期的 todate <<,则没有交互。起始日期,或检查日期的起始日期 >迄今为止。这是假设 check.from <= check.to。

Periods.Any(p => !(check.ToDate < p.FromDate || check.FromDate > p.ToDate));

或(打开底片后):

Periods.Any(p => check.ToDate >= p.FromDate && check.FromDate <= p.ToDate));

Approach it this way instead: There is no intersaction if the check date's todate < the from date, or the check date's fromdate > the to date. This is assuming check.from <= check.to.

Periods.Any(p => !(check.ToDate < p.FromDate || check.FromDate > p.ToDate));

or (after unwrapping the negative):

Periods.Any(p => check.ToDate >= p.FromDate && check.FromDate <= p.ToDate));
终难愈 2024-11-04 21:44:01

如果 FromDate <= ToDate 对于您的 Period 对象始终成立,您可以定义一个帮助器 扩展方法 OverlapsWith 如下:

public static bool OverlapsWith(this Period a, Period b)
{
    return !(b.ToDate <= a.FromDate || a.ToDate <= b.FromDate);
}

为了说明发生了什么,我们看一下在ab之间<​​em>没有重叠的两种情况:

//                         a
//                |-----------------|
//   |--------|                          |-----------|
//       b1                                    b2

您可以对照此图检查上述情况。由于该图显示了没有发生重叠的情况,但该方法确实应该测试重叠,因此需要否定该条件。它可以简化为以下内容:

           b.ToDate > a.FromDate && a.ToDate > b.FromDate

当您在 LINQ 查询中使用此方法时,结果非常容易理解:

    Periods.Any(period => period.OverlapsWith(periodToCheck))

If FromDate <= ToDate always holds true for your Period objects, you can define a helper extension method OverlapsWith as follows:

public static bool OverlapsWith(this Period a, Period b)
{
    return !(b.ToDate <= a.FromDate || a.ToDate <= b.FromDate);
}

To illustrate what's going on, let's look at the two cases where there is no overlap between a and b:

//                         a
//                |-----------------|
//   |--------|                          |-----------|
//       b1                                    b2

You can check the above condition against this diagram. Since the diagram shows the cases where no overlap occurs, but the method really ought to test for overlap, the condition needs to be negated. It could be simplified to the following:

           b.ToDate > a.FromDate && a.ToDate > b.FromDate

When you use this method in a LINQ query, it turns out very easy to understand:

    Periods.Any(period => period.OverlapsWith(periodToCheck))
一场信仰旅途 2024-11-04 21:44:01

您可能会发现以下文章很有用,尤其是TimePeriodIntersector 类。

样本摘录:

public void TimePeriodIntersectorSample()
{
    TimePeriodCollection periods = new TimePeriodCollection();

    periods.Add( new TimeRange( new DateTime( 2011, 3, 01 ), new DateTime( 2011, 3, 10 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 05 ), new DateTime( 2011, 3, 15 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 12 ), new DateTime( 2011, 3, 18 ) ) );

    periods.Add( new TimeRange( new DateTime( 2011, 3, 20 ), new DateTime( 2011, 3, 24 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 22 ), new DateTime( 2011, 3, 28 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 24 ), new DateTime( 2011, 3, 26 ) ) );

    TimePeriodIntersector<TimeRange> periodIntersector = 
                    new TimePeriodIntersector<TimeRange>();
    ITimePeriodCollection intersectedPeriods = periodIntersector.IntersectPeriods( periods );

    foreach ( ITimePeriod intersectedPeriod in intersectedPeriods )
    {
        Console.WriteLine( "Intersected Period: " + intersectedPeriod );
    }
    // > Intersected Period: 05.03.2011 - 10.03.2011 | 5.00:00
    // > Intersected Period: 12.03.2011 - 15.03.2011 | 3.00:00
    // > Intersected Period: 22.03.2011 - 26.03.2011 | 4.00:00
} // TimePeriodIntersectorSample

You may find the following article useful and especially the TimePeriodIntersector class.

Sample excerpt:

public void TimePeriodIntersectorSample()
{
    TimePeriodCollection periods = new TimePeriodCollection();

    periods.Add( new TimeRange( new DateTime( 2011, 3, 01 ), new DateTime( 2011, 3, 10 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 05 ), new DateTime( 2011, 3, 15 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 12 ), new DateTime( 2011, 3, 18 ) ) );

    periods.Add( new TimeRange( new DateTime( 2011, 3, 20 ), new DateTime( 2011, 3, 24 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 22 ), new DateTime( 2011, 3, 28 ) ) );
    periods.Add( new TimeRange( new DateTime( 2011, 3, 24 ), new DateTime( 2011, 3, 26 ) ) );

    TimePeriodIntersector<TimeRange> periodIntersector = 
                    new TimePeriodIntersector<TimeRange>();
    ITimePeriodCollection intersectedPeriods = periodIntersector.IntersectPeriods( periods );

    foreach ( ITimePeriod intersectedPeriod in intersectedPeriods )
    {
        Console.WriteLine( "Intersected Period: " + intersectedPeriod );
    }
    // > Intersected Period: 05.03.2011 - 10.03.2011 | 5.00:00
    // > Intersected Period: 12.03.2011 - 15.03.2011 | 3.00:00
    // > Intersected Period: 22.03.2011 - 26.03.2011 | 4.00:00
} // TimePeriodIntersectorSample
双马尾 2024-11-04 21:44:01

两个具有共同日期的时间段(例如时间段 1 的 ToDate 和时间段 2 的 FromDate)是否相同,算作交集吗?

如果是,那么对您的查询进行一些修改,以简单地检查一个期间的日期是否在单独检查的期间内,就好像其中一个日期落在一个期间内,然后存在交集:

bool conflict = Periods.Any(p => ((p.FromDate >= periodToCheck.fromDate && 
                                    p.ToDate <= periodToCheck.fromDate)
                                  ||
                                   (p.FromDate >= periodToCheck.toDate && 
                                    p.ToDate <= periodToCheck.toDate))
                             );

Do 2 periods having common date, say ToDate for period 1 and FromDate of period 2 are the same, count as in intersection ?

If yes then a little modification to your query to simply check the dates of a period if are within the checked period separately as if one of the dates falls inside a period then there is intersection:

bool conflict = Periods.Any(p => ((p.FromDate >= periodToCheck.fromDate && 
                                    p.ToDate <= periodToCheck.fromDate)
                                  ||
                                   (p.FromDate >= periodToCheck.toDate && 
                                    p.ToDate <= periodToCheck.toDate))
                             );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文