2011-01-03 1 views
2

У меня есть набор объектов, который содержит следующие данные:объектов вставить в коллекцию с помощью LINQ, основанных на свойстве существующих объектов в коллекции

 
FromTime     Duration 

2010-12-28     24.0000 

2010-12-29     24.0000 

2010-12-30     24.0000 

2010-12-31     22.0000 

2011-01-02     1.9167 

2011-01-03     24.0000 

2011-01-04     24.0000 

2011-01-05     24.0000 

2011-01-06     24.0000 

2011-01-07     22.0000 

2011-01-09     1.9167 

2011-01-10     24.0000 

В колонке «Fromtime», там являются «пробелами» данных, т.е. 2011-01-01 и 2011-01-08 «отсутствуют». Так что я хотел бы сделать, это пропустить диапазон дат (в этом случае с 2010-12-28 по 2011-01-10) и «заполнить» «отсутствующие» данные продолжительностью 0.

Как я только что начал с LINQ, я чувствую, что это должно быть «довольно» легко, но я не могу понять все правильно. Я читаю книгу «LINQ in Action», но чувствую, что я все еще довольно далеко, прежде чем я смогу решить эту проблему. Поэтому любая помощь была бы высоко оценена.

David

+0

Зачем засорять данные t с пустыми записями? – leppie

+0

Ну, к сожалению, я должен, потому что я привязываю эти данные к третьему компоненту Silverlight, который требует от меня сделать это, чтобы граф, сгенерированный, выглядел прилично. – DavidS

+0

Должен ли учитываться компонент времени? Например, у вас уже есть '2011-01-02 22: 00: 00.000' в коллекции. Должно ли '2011-01-02 00: 00: 00.000' считать отсутствующим? –

ответ

3

Я определю класс как ниже:

public class DurDate 
{ 
    public DateTime date = DateTime.ToDay; 
    public decimal dure = 0; 
} 

и будет написал функцию как ниже:

private IEnumerable<DurDate> GetAllDates(IEnumerable<DurDate> lstDur) 
    { 

     var min = lstDur.Min(x => x.date).Date; 
     var max = lstDur.Max(x => x.date).Date; 
     var nonexistenceDates = Enumerable.Range(0, (int) max.Subtract(min).TotalDays) 
      .Where(x =>!lstDur.Any(p => p.date.Date == min.Date.AddDays(x))) 
      .Select(p => new DurDate {date = min.Date.AddDays(p), dure = 0}); 

     return lstDur.Concat(nonexistenceDates).OrderBy(x=>x.date); 
    } 

Примеры тестов случай:

List<DurDate> lstDur = new List<DurDate> { new DurDate { date = DateTime.Today, dure = 10 }, new DurDate { date = DateTime.Today.AddDays(-5), dure = 12 } }; 

Edit: Он работает просто, сначала я найду минимальный и максимальный диапазон:

var min = lstDur.Min(x => x.date).Date; 
var max = lstDur.Max(x => x.date).Date; 

Какие дни не в заданном диапазоне:

Where(x =>!lstDur.Any(p => p.date.Date == min.Date.AddDays(x))) 

После нахождения этого дня, я собираюсь выбрать их:

Select(p => new DurDate {date = min.Date.AddDays(p), dure = 0}) 

наконец сцепить начальные значения к этому списку (и отсортировать их):

lstDur.Concat(nonexistenceDates).OrderBy(x=>x.date); 
+0

Спасибо Саид. Ваш код работал, и ваше объяснение того, что сделал код, было очень ясно специально для начинающего LINQ, такого как я. – DavidS

+0

Извините, но не сделал, но я сделал это сейчас. :). Btw какие-либо советы, кроме того, что уже доступно на SO, о том, какие лучшие ресурсы для обучения LINQ, по вашему мнению? – DavidS

+0

@DavidS, http://msdn.microsoft.com/en-us/vcsharp/aa336746 хорош для запуска, после этого, если вы хотите улучшить свои навыки, вы должны прочитать некоторые книги, такие как http://www.amazon.com/ Professional-LINQ-Programmer-Scott-Klein/dp/0470041811/ref = ntt_at_ep_dpt_1 –

1

Что-то в этом роде. Я не проверял, но я считаю, что вы получили идею:

var data = new[] 
       { 
        new { Date = DateTime.Now.AddDays(-5), Duration = 3.56 }, 
        new { Date = DateTime.Now.AddDays(-3), Duration = 3.436 }, 
        new { Date = DateTime.Now.AddDays(-1), Duration = 1.56 }, 
       }; 

    Func<DateTime, DateTime, IEnumerable<DateTime>> range = (DateTime from, DateTime to) => 
       { 
        List<DateTime> dates = new List<DateTime>(); 
        from = from.Date; 
        to = to.Date; 
        while (from <= to) 
        { 
         dates.Add(from); 
         from = from.AddDays(1); 
        } 
        return dates; 
       }; 

    var result = range(data.Min(e => e.Date.Date), data.Max(e => e.Date.Date)) 
     .Join(data, e => e.Date.Date, e => e.Date, (d, x) => new { 
                    Date = d, 
                    Duration = x == null 
                     ? 0.0 
                     : x.Duration 
                   }); 

Кроме того, было бы лучше заменить этот диапазон лямбда с некоторым статическим методом.

+0

Спасибо, что нашли время, чтобы прочитать вопрос и дать ответ. Код работал, но ответ Саида мне легче понять, и именно поэтому я выбрал его ответ заранее. – DavidS