Getting odd/even part of a sequence with LINQ

Say I have a list of all Projects, and that I group them by Category like this:

var projectsByCat = from p in Projects
                    group p by p.Category into g
                    orderby g.Count() descending
                    select new { Category = g.Key, Projects = g };

Now I want to display this as a list in a web page, where first I create the left side div, secondly the right side div. I am ordering by number of Projects in each Category to show the Categories with the most Projects on top - thus I would like to split projectsByCat in two - if I put all the "odd numbered" Categories on the left and the "even numbered" categories on the right, I think I will get a reasonably sane view.

So I thought I could do this to get the odd and even members of projectsByCat:

var oddCategories = projectsByCat.Where((cat, index) => index % 2 != 0);

var evenCategories = projectsByCat.Where((cat, index) => index % 2 == 0);

And it compiles - however, when I run it, I get an exception such as this:

Unsupported overload used for query operator 'Where'.

And I thought I was safe since it compiled in the first place.. ;)

Is there an elegant way to do this? And also, is there an elegant explanation for why my creative use of Where() won't work?

Thanks in advance!


Solution 1:

If you're using LINQ to SQL or LINQ to Entities you should first fully materialize the results into memory:

var oddCategories  = projectsByCat.ToList().Where((c,i) => i % 2 != 0);
var evenCategories = projectsByCat.ToList().Where((c,i) => i % 2 == 0);

It isn't possible to iterate through results on the database with an indexer without the use of a cursor, which either ORM framework does not do.

Solution 2:

Note that calling .ToList() twice for the same query is going query the database twice.

It would be much better to cache the result in an intermediate list, then apply your predicate filtering:

var projectsByCat =
    (from p in Projects
    group p by p.Category into g
    orderby g.Count() descending
    select new { Category = g.Key, Projects = g }).ToList();

var oddCategories = projectsByCat.Where((cat, index) => index % 2 != 0);
var evenCategories = projectsByCat.Where((cat, index) => index % 2 == 0);