Reputation: 13557
In my code I need to sort a collection either by Price or by Rating.TotalGrade and as you can see both LINQ querys are almost the same statement with only a minor difference.
I was thinking about using a LINQ predicate instead but as you can see the the orderby is the main difference and I found no sample using orderby in a query. Is it possible or are there other ways to shorten my code, Maybe there will be even more conditions in the future.
if (CurrentDisplayMode == CRSChartRankingGraphDisplayMode.Position)
{
this.collectionCompleteSorted = new List<Result>(from co in collection
where co.IsVirtual == false
orderby co.Price, co.CurrentRanking
select co);
}
else if (CurrentDisplayMode == CRSChartRankingGraphDisplayMode.Grade)
{
this.collectionCompleteSorted = new List<Result>(from co in collection
where co.IsVirtual == false
orderby co.Rating.TotalGrade, co.CurrentRanking
select co);
}
Upvotes: 2
Views: 8485
Reputation: 20194
var q = collection.Where(co => !co.IsVirtual);
if (CurrentDisplayMode == CRSChartRankingGraphDisplayMode.Position)
{
q = q.OrderBy(co => co.Price).ThenBy(co => co.CurrentRanking);
}
else if (CurrentDisplayMode == CRSChartRankingGraphDisplayMode.Grade)
{
q = q.OrderBy(co => co.Rating.TotalGrade).ThenBy(co => co.CurrentRanking);
}
this.collectionCompleteSorted = q.ToList();
Upvotes: 1
Reputation: 12849
You can easily make use of deffered nature of LINQ and ability to easily compose queries.
Probably using code like this:
var baseQuery = from co in collection where !co.IsVirtual select co; // base of query
IOrderedEnumerable<Result> orderedQuery; // result of first ordering, must be of this type, so we are able to call ThenBy
switch(CurrentDisplayMode) // use enum here
{ // primary ordering based on enum
case CRSChartRankingGraphDisplayMode.Position: orderedQuery = baseQuery.OrderBy(co => co.Price);
break;
case CRSChartRankingGraphDisplayMode.Grade: orderedQuery = baseQuery.OrderBy(co => co.TotalGrade);
break;
}
this.collectionCompleteSorted = orderedQuery.ThenBy(co => co.CurrentRanking).ToList(); // secondary ordering and conversion to list
Its easy to understand and avoids converting to list until the very end.
Upvotes: 3
Reputation: 101614
Why not just grab the values (less the sort), then (as it appears) use a case to order the results?
// build your collection first
var items = from co in collection
where !co.IsVirtual
select co;
// go through your sort selectors
select (CurrentDisplayMode)
{
case CRSChartRankingGraphDisplayMode.Position:
this.collectionCompleteSorted = items.OrderBy(i => i.Price).ThenBy(j => j.CurrentRanking).ToList();
break;
case CRSChartRankingGraphDisplayMode.Grade:
this.collectionCompleteSorted = items.OrderBy(i => i.TotalGrade).ThenBy(j => j.CurrentRanking).ToList();
break;
...
//default: // maybe you want this, too
}
Upvotes: 1
Reputation: 13057
If just your order by is different, than return your result into this.collectionCompleteSorted, and then do this.collectionCompleteSorted.OrderBy() when you enumerate through the data.
this.collectionCompleteSorted = new List<Result>(from co in collection
where co.IsVirtual == false
select co);
foreach (var obj in this.collectionCompleteSorted.OrderBy(c => c.Price).ToList())
{
// do something
}
And remove the order by remove your current linq query.
If the query is just being executed once, than you can leave off the .ToList() from the linq query in the example above. When ToList is called, this causes the query to be executed immediately, where if the OrderBy is implemented in a later call to the collection and a ToList is also, than the query would actually be executed on the database server with an order by statement, offloading the ordering from the code to the database. See http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx
Upvotes: 1