Reputation: 10081
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?
Upvotes: 31
Views: 50635
Reputation: 391594
The proper way to do this using LINQ, and avoiding multiple enumerations over the input, is to do a grouping or similar on whether each item is even or odd.
A simple way using the overload for Select
that mixes in an index coupled with ToLookup
gives you what you want:
var oddsAndEvens = input
.ToList() // if necessary to get from IQueryable to IEnumerable
.Select((item, index) => new { isEven = index % 2 == 0, item })
.ToLookup(
i => i.isEven,
i => i.item);
This will produce a Lookup<TKey, TElement>
data structure that has the following benefit:
If the key is not found in the collection, an empty sequence is returned.
This means that after the above LINQ query you can do:
var evens = oddsAndEvens[true];
var odds = oddsAndEvens[false];
Upvotes: 4
Reputation: 1
Using Linq GroupBy Method:
List<string> lista = new List<string> { "uno", "dos", "tres", "cuatro" };
var grupoXindices = lista.GroupBy(i => (lista.IndexOf(i) % 2) == 0);
foreach (var grupo in grupoXindices)
{
Console.WriteLine(grupo.Key);
foreach (var i in grupo) Console.WriteLine(i);
}
Upvotes: 0
Reputation: 1146
var text = "this is a test <string> to extract odd <index> values after split";
var parts = text.Split(new char[] { '<', '>' });
IEnumerable words = parts.Where(x => parts.ToList().IndexOf(x) % 2 == 1)
words would contain "string" and "index"
Upvotes: 0
Reputation: 9
You Can find Even odd number without foreach loop
static void Main(string[] args)
{
List<int> lstnum = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
List<int> lstresult = lstnum.FindAll(x => (x % 2) == 0);
lstresult.ForEach(x => Console.WriteLine(x));
}
Upvotes: 0
Reputation: 450
You can separate odd and even in your view using linq.
//even
@foreach (var item in Model.Where((item, index) => index % 2 == 0))
{
//do the code
}
//odd
@foreach (var item in Model.Where((item, index) => index % 2 != 0))
{
//do the code
}
Upvotes: 2
Reputation: 410
The oddCategories and the evenCategories are backward.
Indexes start a 0 not 1
0 % 2 = 0
0 index is odd.
var oddCategories = projectsByCat.Where((cat, index) => index % 2 == 0);
var evenCategories = projectsByCat.Where((cat, index) => index % 2 != 0);
Upvotes: 5
Reputation: 4132
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);
Upvotes: 26
Reputation: 100027
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.
Upvotes: 53