c#限制连续项目 - Linq

时间:2015-11-09 15:58:06

标签: c# linq list date

我们假设我有一个日期列表

01/01/2014,02/01/2014,08/01/2014,10/01/2014,11/01/2014,12/01/2014

如何获得连续项目的限制:

在我们的案例中应该是:

[01/01/2014,02/01/2014],
[08/01/2014],
[10/01/2014,12/01/2014]

我更喜欢Linq的解决方案。

3 个答案:

答案 0 :(得分:2)

我不认为LINQ有一个优雅/简单的解决方案。但循环可以做到这一点:

List<DateTime> dates = new List<DateTime>() {
    new DateTime(2014, 1, 1),
    new DateTime(2014, 1, 2),
    new DateTime(2014, 1, 8),
    new DateTime(2014, 1, 10),
    new DateTime(2014, 1, 11),
    new DateTime(2014, 1, 12)
};
List<List<DateTime>> limits = new List<List<DateTime>>();

foreach (DateTime date in dates)
{
    if (!limits.Any() || limits.Last().Last().AddDays(1) < date)
    {
        // add new limit group with the current date as startdate
        limits.Add(new List<DateTime>() { date });
    }
    else
    {
        if (limits.Last().Count == 1)
        {
            // add the current date as new end date for the last limit group
            limits.Last().Add(date);
        }
        else
        {
            // replace end date from last limit group with the current date
            limits.Last()[1] = date;
        }
    }
}

答案 1 :(得分:2)

这可以在Linq中完成,这是一个完整的工作示例: 只是证明这是可能的,而不是说它是个好主意......

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;

namespace Sandbox
{
    public class Program
    {
        public static void Main(string[] args)
        {
            List<DateTime> dates = new List<DateTime>();
            dates.Add(new DateTime(2014, 1, 1));
            dates.Add(new DateTime(2014, 1, 2));
            dates.Add(new DateTime(2014, 1, 8));
            dates.Add(new DateTime(2014, 1, 10));
            dates.Add(new DateTime(2014, 1, 11));
            dates.Add(new DateTime(2014, 1, 12));


            var values = 
            dates.Select(dt => new DateRange(dt, dt))
                .Distinct(new DateConsecutiveComparer()).ToArray();

            foreach (var range in values)
            {
                Console.WriteLine(range);
            }

            Console.ReadKey();
        }
    }

    public class DateRange
    {
        public DateTime End { get; set; }
        public DateTime Start { get; set; }

        public DateRange(DateTime end, DateTime start)
        {
            End = end;
            Start = start;
        }

        public override string ToString()
        {
            if (Start == End)
                return "[" + Start.ToString("MM/dd/yyyy") + "]";
            return "[" + Start.ToString("MM/dd/yyyy") + "," + End.ToString("MM/dd/yyyy") + "]";
        }

        public override int GetHashCode()
        {
            return Tuple.Create(Start, End).GetHashCode();
        }
    }

    public class DateConsecutiveComparer : IEqualityComparer<DateRange>
    {
        public bool Equals(DateRange x, DateRange y)
        {
            if (x.End.AddDays(1) == y.Start)
            {
                x.End = y.End;
                return true;
            }
            else if (y.End.AddDays(1) == x.Start)
            {
                y.End = x.End;
                return true;
            }

            else
                return false;
        }

        public int GetHashCode(DateRange obj)
        {
            return 1;
        }
    }
}

答案 2 :(得分:0)

代码不简单。无法用Linq实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;

namespace ConsoleApplication56
{
    class Program
    {
        static void Main(string[] args)
        {
            List<DateTime> dates = new List<DateTime>(){
                DateTime.Parse("01/01/2014"),
                DateTime.Parse("02/01/2014"),
                DateTime.Parse("08/01/2014"),
                DateTime.Parse("10/01/2014"),
                DateTime.Parse("11/01/2014"),
                DateTime.Parse("12/01/2014")
            }.OrderBy(x => x).ToList();

            List<DateRange> ranges = new List<DateRange>();
            DateTime previousDate = new DateTime();
            DateRange newRange = null;
            for (int index = 0; index < dates.Count; index++)
            {
                if (index == 0)
                {
                    previousDate = dates[0];
                    newRange = new DateRange() { startDate = dates[index]};
                    ranges.Add(newRange);
                }
                else
                {
                    if (index == dates.Count - 1)
                    {
                        if (IsConsecutive(previousDate, dates[index]))
                        {
                            newRange.endDate = dates[index];
                        }
                        else
                        {
                            if (index != 1)
                            {
                                newRange.endDate = dates[index - 1];
                            }
                            newRange = new DateRange() { startDate = dates[index] };
                            ranges.Add(newRange);
                        }
                    }
                    else
                    {
                        if (!IsConsecutive(previousDate, dates[index]))
                        {
                            if (index != 1)
                            {
                                if(newRange.startDate != dates[index - 1])
                                   newRange.endDate = dates[index - 1];
                            }
                            newRange = new DateRange() { startDate = dates[index] };
                            ranges.Add(newRange);
                        }
                        previousDate = dates[index];
                    }
                }
            }
        }

        static Boolean IsConsecutive(DateTime firstDate, DateTime secondDate)
        {
            if((new DateTime(firstDate.Year, firstDate.Month, 1)).AddMonths(1) == (new DateTime(secondDate.Year, secondDate.Month, 1)))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

    }
    public class DateRange
    {
        public DateTime startDate { get; set; }
        public DateTime endDate { get; set; }
    }
}