I have a large unsorted list of items. Some items are important and need to listed first, followed by unimportant items. The items should be sorted by name in the two groups. I have a solution, but I believe it can be optimized. First, it gets a list of important items. Then a list of everything else, then concatenates the results. Any suggestions on how to optimize this?
Here is a simplified version of the problem for LINQPad:
var doc = XDocument.Parse(@"
<items>
<item id='a'>not important4</item>
<item id='b'>important2</item>
<item id='c'>not important2</item>
<item id='d'>not important3</item>
<item id='e'>important1</item>
<item id='f'>not important1</item>
</items>");
// identify which items are important
string[] importantItemIDs = new string[] { "b", "e" };
var items = doc.Root.Elements("item");
// get a list of important items (inner join)
var importantList = from itemID in importantItemIDs
from item in items
orderby (string) item.Value
where itemID == (string) item.Attribute("id")
select item;
// get items that are not important items
var notImportantList = items.Except(importantList).OrderBy(i => (string) i.Value);
// concatenate both sets of results into one list
var fullList = importantList.Concat(notImportantList);
fullList.Select(v => v.Value).Dump();
Here’s the correct output:
important1
important2
not important1
not important2
not important3
not important4
One approach that immediately comes to mind is to utilize OrderBy as well as ThenBy to avoid querying the original data source multiple times. Something like:
I’m not sure if the ternary operator is necessary there – I forget how OrderBy deals with boolean results. Shouldn’t be a major performance concern anyway and is potentially a bit clearer.