LINQ查询优化?

3

我有一个未排序的大型项目列表。其中一些项目很重要,需要首先列出,然后是不重要的项目。这些项目应按名称在两个组中排序。我有一个解决方案,但我认为它可以优化。首先,它获取重要项目列表。然后获取其他所有内容的列表,然后连接结果。有什么建议可以优化吗?

以下是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();

这是正确的输出结果:
important1
important2
not important1
not important2
not important3
not important4

你希望如何进行优化?是为了执行的速度吗? - Robert Harvey
是的,也许可以用更少的代码实现,但我更关心性能。 - soconnor
现在运行速度太慢了吗?还是您试图解决尚未发生的问题? - Robert Harvey
已经实现了,我正在寻求关于解决问题的另一种方法的建议,可能会产生更好的结果。在现实世界中,当项目列表在25,000范围内时,需要大约1200毫秒。在没有分组要求的相同数据集上进行查询的时间范围为100毫秒。这里存在很大的差距,我正在寻找缩小差距的方法。 - soconnor
2个回答

5

一个立即想到的方法是利用 OrderBy 和 ThenBy 来避免多次查询原始数据源。类似这样:

var list = items
       .OrderBy(i => importantItemIDs.Contains(i.Attribute("id") ? 0 : 1)
       .ThenBy(i => i.Value);
       .Select(i => i.Value);

我不确定三元运算符是否必要 - 我忘记了OrderBy如何处理布尔结果。这不应该是一个主要的性能问题,而且可能会更清晰一些。


到目前为止发布的两个答案都显著提高了原始性能,并且表现得同样出色。这个答案因为更加优雅而受到青睐。谢谢。 - soconnor

1
var prioritized = 
        from item in items 
        select new {
        Importance = importantItemIDs.Contains((string) item.Attribute)? 1 :2,
        Item = item
        };

var fullList =   from pitem in prioritized 
                 orderby pitem.Importance, pitem.Item.Value
                 select pitem.Item.Value;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接