Найти диапазон дат из коллекции дат C # - PullRequest
1 голос
/ 25 августа 2010

Простой вопрос.У меня есть заказанная коллекция дат.Это британские даты между прочим

01/01/10
01/02/10
01/03/10
01/04/10
02/04/10
03/04/10
04/04/10

И я хочу преобразовать это в набор диапазонов дат

01/01/10 -> 01/01/10
01/02/10 -> 01/02/10
01/03/10 -> 01/03/10
01/04/10 -> 04/04/10

Просто чтобы уточнить, я пытаюсь преобразовать любые последовательные даты вспектр.поэтому первые 3 даты являются самостоятельными, а последние 4 преобразуются в диапазон с 1 апреля по 4 апреля.

Теперь я могу сделать это с помощью циклов, но это не очень элегантно.У кого-нибудь есть какие-нибудь решения, которые есть?

Спасибо

Ответы [ 3 ]

5 голосов
/ 25 августа 2010

Учитывая, что вы хотите определить диапазоны последовательных диапазонов дат, я думаю, что ваш единственный вариант, как вы говорите, цикл. Вы можете сделать это за один проход и поместить его в метод расширения, чтобы он работал на любом IList<DateTime>, например:

// purely an example, chances are this will have actual, y'know logic in live
public class DateRange
{
    private List<DateTime> dates = new List<DateTime>();

    public void Add(DateTime date)
    {
        this.dates.Add(date);
    }

    public IEnumerable<DateTime> Dates
    {
        get { return this.dates; }
    }
}

public static IEnumerable<DateRange> GetRanges(this IList<DateTime> dates)
{
    List<DateRange> ranges = new List<DateRange>();
    DateRange currentRange = null;

    // this presumes a list of dates ordered by day, if not then the list will need sorting first
    for( int i = 0; i < dates.Count; ++i )
    {
        var currentDate = dates[i];
        if( i == 0 || dates[i - 1] != currentDate.AddDays(-1))
        {
            // it's either the first date or the current date isn't consecutive to the previous so a new range is needed
            currentRange = new DateRange();
            ranges.Add(currentRange);
        }

        currentRange.Add(currentDate);
    }

    return ranges;
}

Вы также можете сделать его еще более универсальным, передав IEnumerable<DateTime>:

public static IEnumerable<DateRange> GetRanges(this IEnumerable<DateTime> dates)
{
    List<DateRange> ranges = new List<DateRange>();
    DateRange currentRange = null;
    DateTime? previousDate = null;

    // this presumes a list of dates ordered by day, if not then the list will need sorting first
    foreach( var currentDate in dates )
    {
        if( previousDate == null || previousDate.Value != currentDate.AddDays(-1) )
        {
            // it's either the first date or the current date isn't consecutive to the previous so a new range is needed
            currentRange = new DateRange();
            ranges.Add(currentRange);
        }

        currentRange.Add(currentDate);
        previousDate = currentDate;
    }

    return ranges;
}
0 голосов
/ 25 августа 2010
dates.Aggregate(new List<DateRange>(), (acc, dt) =>
                                       {
                                         if (acc.Count > 0 && acc.Last().d2 == dt.AddDays(-1))
                                           acc[acc.Count - 1].d2 = dt;
                                         else
                                           acc.Add(new DateRange(dt, dt));
                                         return acc;
                                       }
    );

, где DateRange такой класс:

class DateRange
{
  public DateTime d1, d2;

  public DateRange(DateTime d1, DateTime d2)
  {
    this.d1 = d1;
    this.d2 = d2;
  }
}
0 голосов
/ 25 августа 2010
var stringDates = new List<string> {"01/09/10", "31/08/10", "01/01/10"};

var dates = stringDates.ConvertAll(DateTime.Parse);
dates.Sort();

var lastDateInSequence = new DateTime();
var firstDateInSequence = new DateTime();  

foreach (var range in dates.GroupBy(
    d => { if ((d - lastDateInSequence).TotalDays != 1)   
               firstDateInSequence = d;  
           lastDateInSequence = d;
           return firstDateInSequence;  
         }))
    {
        var sb = new StringBuilder();
        sb.Append(range.First().ToShortDateString());
        sb.Append(" => ");
        sb.Append(range.Last().ToShortDateString());
        Console.WriteLine(sb.ToString());
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...