用于解密连续日期范围的逻辑

时间:2015-09-28 19:38:08

标签: c# linq logic

说我有一个类Slots如下

public class Slots
{
   //Other properties
    .
    .
    .
    public DateTime StartTime{get;set;}
    public DateTime EndTime{ge;set;}
    //Methods
}

我有List<Slots>,确定连续Slotgroups的最有效方法是什么? 连续时隙被定义为相对于前一时隙在第二天开始的任何时隙组,没有重叠。 如果有一天的间隔(列表中当天没有插槽),则应将其视为另一个插槽组的开始。

public List<List<Slots>> GetSlotGroups(List<SLots> slots)
{
    //return  list of slot groups according to logic described above
}

4 个答案:

答案 0 :(得分:2)

使用GetEnumerator可以最好地实现这种操作。 以下代码需要对列表进行排序。

IEnumerable<IEnumerable<Slot>> ToGroups(IEnumerable<Slot> slots)
{
    using (var ie = slots.GetEnumerator())
    {
        var range = new List<Slot>();
        while (ie.MoveNext())
        {
            if (range.Count > 0)
            {
                if (ie.Current.Start > range[range.Count - 1].End)
                {
                    yield return range;
                    range = new List<Slot>{ie.Current};
                    continue;
                }
            }
            range.Add(ie.Current);
        }
        yield return range;
    }
}

答案 1 :(得分:1)

这是我提出的代码。我不知道它是否效率最高,但它的可读性和速度相当快。

    public static List<List<Slots>> GetGroups(List<Slots> slots)
    {
        List<List<Slots>> groups = new List<List<Slots>>();
        DateTime? nextDate = null;
        List<Slots> currentGroup = null;

        foreach (var slot in slots.OrderBy(x => x.StartDate))
        {
            //first time through nextDate and currentGroup are null
            //this condition matches the first time through or any time there is a gap in dates
            if (nextDate == null || nextDate.Value < slot.StartDate)
            {
                if (currentGroup != null)
                {
                    //if currentGroups isn't null then we have a completed group
                    groups.Add(currentGroup);
                }
                //start a new group
                currentGroup = new List<Slots>();
            }
            nextDate = slot.EndDate.AddDays(1);
            currentGroup.Add(slot);
        }

        //if there are no items in the collection currentGroup will still be null, otherwise currentGroup has the last group in it still. We finished iterating before finding a gap in dates
        if (currentGroup != null)
        {
            groups.Add(currentGroup);
        }

        return groups;
    }

此代码通过在前一个广告位的结束日期中添加一个来跟踪范围中的下一个日期。当我们从一个槽到另一个槽时,我们附加到一个名为currentGroup的临时列表。当我们的下一个日期小于当前插槽的开始日期时,我们将当前组添加到名为groups的结果列表中,并为当前组创建新列表。最后,我们可能在最后一组的currentGroup中有一些插槽,所以我们也必须添加那个插槽。

答案 2 :(得分:1)

很简单。按StartTime排序,然后迭代排序集,如果当前项不是与前一项连续,则添加新组并使其成为当前项。然后只需将项目添加到当前组。

public static List<List<Slots>> GetSlotGroups(List<Slots> slots)
{
    var slotGroups = new List<List<Slots>>();
    using (var e = slots.OrderBy(slot => slot.StartTime).GetEnumerator())
    {
        List<Slots> currentGroup = null;
        Slots lastSlot = null;
        while (e.MoveNext())
        {
            var currentSlot = e.Current;
            if (lastSlot == null || currentSlot.StartTime.Date.Subtract(lastSlot.EndTime.Date).Days > 1)
                slotGroups.Add(currentGroup = new List<Slots>());
            currentGroup.Add(currentSlot);
            lastSlot = currentSlot;
        }
    }
    return slotGroups;
}

答案 3 :(得分:0)

最佳答案是基于George的代码和Roberts评论,但经过修改后考虑在某一天有多个插槽。

 protected IEnumerable<IEnumerable<ExamCalendar>>ToBlocks(IEnumerable<ExamCalendar> slots)
    {
        using (var ie = slots.OrderBy(slot => slot.StartDate).GetEnumerator())
        {
            var block = new List<ExamCalendar>();
            while (ie.MoveNext())
            {
                if (block.Count > 0)
                {
                    if (ie.Current.StartDate.Date != block[block.Count - 1].StartDate.Date && ie.Current.StartDate.Date != block[block.Count - 1].EndDate.AddDays(1).Date)
                    {
                        yield return block;
                        block = new List<ExamCalendar> { ie.Current };
                        continue;
                    }
                }
                block.Add(ie.Current);
            }
            yield return block;
        }
    }