2013-02-21 1 views
0

У меня есть коллекция DateTime объектов. Мне нужно «разобрать» подколлекции из этого исходного списка, чтобы захватить связанные элементы на основе повторения. Поэтому мне нужно, чтобы принять эту единственную оригинальную коллекцию:Ищете алгоритм C# для захвата повторяющихся элементов из коллекции объектов DateTime (факторинг как по дате, так и по времени)?

var collectionOfDateTime = GetDateTimeCollection(); 

и перевести это в список DateTime коллекций, где каждая коллекция включает в себя набор дат из первого списка, после конкретного шаблона рецидива.

В моих примерах ниже я не включаю время, но в реальном требовании эти элементы имеют для них элементы даты и времени. Так, например, Даты должны быть на 7 дней друг от друга, но также быть одинаковыми (один раз 3 февраля в 11 утра не соответствует 10-м февраля в 3 вечера, но он соответствует 10 февраля в 11:00)

Например , позволяет сказать, что мой рецидив картина «Weekly» (в других случаях это может быть «Ежемесячно») и моя коллекция дата выглядит следующим образом:

var date1 = DateTime.Today.AddHours(8); 
var date2 = DateTime.Today.AddWeeks(1).AddHours(8); 
var date3 = DateTime.Today.AddDays(3); 
var date4 = DateTime.Today.AddWeeks(8).AddHours(6); 

var collectionOfDateTime = new List<DateTime>() { date1, date2, date3, date4 }; 

Я хотел бы функцию (назовем ее StripOutSubCollections()), чтобы пройти в collectionOfDateTime и тот факт, что его «Еженедельно» и возвращают одну коллекцию, которая включает в себя date1, date2 (так как все они являются частью одного и того же недельного слота). Примечание date3 не не подходит и date4 также не подходит, потому что часы не совпадают с другими

Для другого примера, чтобы помочь доказать из требования, если вход в оригинальной коллекции было это:

var date1 = DateTime.Today; 
var date2 = DateTime.Today.AddWeeks(1); 
var date3 = DateTime.Today.AddDays(3); 
var date4 = DateTime.Today.AddWeeks(8); 
var date5 = DateTime.Today.AddDays(3).AddWeeks(2); 

var collectionOfDateTime = new List<DateTime>() { date1, date2, date3, date4, date5 }; 

Я хотел бы эту функцию, чтобы вернуть 2 списков (один список с date1, date2 и date4) и еще один список с date3 и date5.

Сообщите мне, если мне нужно больше примеров, чтобы сформулировать требования? Обратите внимание, что возможно, что одна из дат может попадать в несколько выходных списков, что прекрасно.

Я могу конвертировать еженедельно в число 7 и прокручивать каждый элемент, начиная с первого элемента до конца, затем второго элемента до конца, затем третьего элемента и т. Д., Но хотел бы посмотреть, более изящный способ

+1

В вашей первой Например, не 'date3', не' date2', нечетный человек? – HABO

+0

@Brian - я обновил свой нынешний подход грубой силы, который, кажется, работает нормально, но чувствует, что может быть более элегантный способ – leora

+0

@HABO - да, это была опечатка, исправленная – leora

ответ

2

Если я правильно понял ваш вопрос, вы пытаетесь «обрезать» значения DateTime к Дню недели?

Если это так, что-то вроде этого следует сделать это:

var byDayOfWeek = collectionOfDateTime.GroupBy(dt => dt.DayOfWeek); 
// Optionally convert to a dictionary by day of week 
var asDict = byDayOfWeek.ToDictionary(grp => grp.Key, grp => grp.ToList()); 

foreach(var kvp in asDict) 
{ 
    Console.WriteLine("Day:" + kvp.Key); 
    foreach (var value in kvp.Value) 
    { 
     Console.WriteLine(value); 
    } 
} 

Выход:

Day:Thursday 
2/21/2013 12:00:00 AM 
2/28/2013 12:00:00 AM 
4/18/2013 12:00:00 AM 
Day:Sunday 
2/24/2013 12:00:00 AM 

EDIT: Для нескольких "группировка по" правилам:

public enum ChunkType 
{ 
    Weekly, 
    Monthly, 
    Yearly 
} 

public IEnumerable<IEnumerable<DateTime>> ChunkDates(IEnumerable<DateTime> collection, ChunkType chunkBy) 
{ 
    switch(chunkBy) 
    { 
     case ChunkType.Weekly: 
      // roughly equals by day of week 
      return collection.GroupBy(dt => dt.DayOfWeek).Select(grp => grp.ToList()); 
     case ChunkType.Monthly: 
      // Trickier - assume by ordinal day of month? 
      return collection.GroupBy(dt => dt.Day).Select(grp => grp.ToList()); 
     case ChunkType.Yearly: 
      // Trickier - assume by ordinal day of year? 
      return collection.GroupBy(dt => dt.DayOfYear).Select(grp => grp.ToList());   
    } 
    return new[]{ collection }; 
} 

var date1 = DateTime.Today; 
var date2 = DateTime.Today.AddDays(7); 
var date3 = DateTime.Today.AddDays(3); 
var date4 = DateTime.Today.AddDays(8*7); 

var collectionOfDateTime = new List<DateTime>() { date1, date2, date3, date4}; 

foreach(var type in new [] { ChunkType.Weekly, ChunkType.Monthly, ChunkType.Yearly }) 
{ 
    Console.WriteLine("Now grouping by:" + type); 
    var grouped = ChunkDates(collectionOfDateTime, type); 
    foreach(var groupOfDates in grouped) 
    { 
     Console.WriteLine("New group!"); 
     foreach (var value in groupOfDates) 
     { 
      Console.WriteLine(value); 
     } 
    } 
} 

Выход:

Now grouping by:Weekly 
New group! 
2/21/2013 12:00:00 AM 
2/28/2013 12:00:00 AM 
4/18/2013 12:00:00 AM 
New group! 
2/24/2013 12:00:00 AM 

Now grouping by:Monthly 
New group! 
2/21/2013 12:00:00 AM 
New group! 
2/28/2013 12:00:00 AM 
New group! 
2/24/2013 12:00:00 AM 
New group! 
4/18/2013 12:00:00 AM 

Now grouping by:Yearly 
New group! 
2/21/2013 12:00:00 AM 
New group! 
2/28/2013 12:00:00 AM 
New group! 
2/24/2013 12:00:00 AM 
New group! 
4/18/2013 12:00:00 AM 
+0

см. Обновленный вопрос. Мне нужно что-то, что факторы во времени (а не только день недели), а также – leora

+0

@leora Проверьте изменения? – JerKimball

+0

спасибо за ответ JerKimball. Извините за несколько обновлений, но я понял, что пропустил часть своего вопроса в исходном сообщении. см. обновленный вопрос. Мне нужно что-то, что влияет во времени (а не только на день недели). Я также обновил этот пример, чтобы объяснить элемент времени – leora

0

Использование LINQ

Try (что-то подобное, это LINQesque псевдо-код)

var datecollections = from d in collectionOfDateTime 
      group d by d.DayOfWeek into g 
      select new { Day = g.Key, Date = g }; 

Дайте, что пойти и посмотреть, где он получает вас ...

+0

см. Обновленный вопрос. Мне нужно что-то, что влияет во времени (а не только на день недели). Я также обновил этот пример, чтобы объяснить элемент времени – leora

0
var dict = new Dictionary<int, List<DateTime>>(); 
foreach (var date in collectionOfDateTime) 
{ 
    if (dict.Contains(date.DayOfWeek)) 
    { 
    dict[date.DayOfWeek].Add(date); 
    } 
    else 
    { 
    dict.Add(date.DayOfWeek, new List<Date> { date }); 
    } 
} 
+0

см. Обновленный вопрос. Мне нужно что-то, что влияет во времени (а не только на день недели). Я также обновил этот пример, чтобы объяснить элемент времени – leora