Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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.

share|improve this question
2  
Do you have an example output that you would like to achieve? – LukeHennerley May 2 at 8:05
what do you mean by "Data contains some gaps" – CodeIgnoto May 2 at 8:12
@CodeIgnoto the question is answered now, but I meant that data would not contain a corresponding value for all of the dates generated, as on some days there would be no views. – roryok May 2 at 10:12
yes on days with no views you get a view count as zero – CodeIgnoto May 2 at 10:15

3 Answers

up vote 1 down vote accepted

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

share|improve this answer
cool, didn't realise I could use a conditional operator within a new statement like that. – roryok May 2 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. – Tim Schmelter May 2 at 12:14

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.

share|improve this answer

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

share|improve this answer
Range is indeed the way to go. – Serge May 2 at 8:43

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.