0

I have two IEnumerables. One contains dates, the other contains data.

DateTime start = DateTime.Today.AddDays(-21);

var dates = Enumerable.Range(0, 21).Select(n => start.AddDays(n)).ToArray();

var data = MyClass.Data.Select(x => new { Date = x.Date, Views = x.Count });

I'm trying to build a table which shows the Views on a given day. However, data contains some gaps. How do I write a linq query which joins the two sets, and returns the Views number when present or 0 when there is no matching object in data?

I can do this the old fashioned way with foreach statements but I'd like to know how to do it in Linq.

sphair
  • 1,674
  • 15
  • 29
roryok
  • 9,325
  • 17
  • 71
  • 138

3 Answers3

1

This should work:

var data = from day in Enumerable.Range(0, 21).Select(n => start.AddDays(n))
           join d in MyClass.Data.Select(x => new { Date = x.Date, Views = x.Count })
           on day equals d.Date into gj
           from dd in gj.DefaultIfEmpty()
           select new { Date = day, Views = dd == null ? 0 : dd.Views };

This returns the views-number when there is one at the given day and 0 otherwise.

How to: Perform Left Outer Joins

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
1

Not sure i fully understood your question.If you want to generate a list of days which has at least one views,then this will get the job done.

DateTime start = DateTime.Today.AddDays(-21);

//Sample view data
var viewsData = new[] {new {id = "id", date = new DateTime(2013, 4, 12), views = 25}};

var dates = Enumerable.Range(0, 21)
                        .Select(d => start.AddDays(d))
                        .Select(n => new
                                        {
                                         Day = n,
                                         views =viewsData.Any(x => x.date == n)
                                         ? viewsData.FirstOrDefault(v => v.date == n).views
                                         : 0
                         });   

Zero is populated for days having no views

Prabhu Murthy
  • 9,031
  • 5
  • 29
  • 36
  • cool, didn't realise I could use a conditional operator within a new statement like that. – roryok May 02 '13 at 10:11
  • Very inefficient. For every date it loops the whole collection to determine if it exists, then it loops it again to find the element. A `Join` is much [more efficient](http://stackoverflow.com/questions/5551264/why-is-linq-join-so-much-faster-than-linking-with-where). – Tim Schmelter May 02 '13 at 12:14
0

Have a look at this MSDN article: http://msdn.microsoft.com/en-us/library/vstudio/bb397895.aspx

It explains how to do a left outer join which is what you need in this case.

Davio
  • 4,609
  • 2
  • 31
  • 58