5

我正在创建一项服务,以使用户可以轻松地从IANA 协议注册表中选择协议。

正如您可能想象的那样,在注册表中搜索该术语会http获得很多点击率。由于amt-soap-http用户选择的频率比直接选择的频率要低得多http,所以我决定最好先提取所有以开头的内容http,然后将其与剩余的结果连接起来。

下面的 lambda 表达式是该思考过程的结果:

var records = this._ianaRegistryService.GetAllLike(term).ToList();
var results = records.Where(r => r.Name.StartsWith(term))
                     .OrderBy(r => r.Name)
                     .Concat(records.Where(r => !r.Name.StartsWith(term))
                                    .OrderBy(r => r.Name))
                     .Take(MaxResultSize);

不幸的是,我觉得我对结果的迭代次数超过了必要的次数。除了过早的优化考虑之外,是否存在比上述更有效的 lambda 表达式组合?

4

2 回答 2

5

两步排序可能更有效:

var results = records.OrderBy(r => r.Name.StartsWith(term) ? 1 : 2)
                     .ThenBy(r => r.Name)
                     .Take(MaxResultSize);
于 2013-02-14T21:32:45.663 回答
3

使用评论来解释我正在尝试做的事情变得越来越难。所以我会发布另一个答案。假设我想首先根据其偶数或奇数对随机整数列表进行排序,然后按数字顺序(StartsWith用模拟mod 2)。

这是测试用例:action2与其他答案相同。

如果您运行此代码,您会发现我的建议 ( action1) 快了两倍。

void Test()
{
    Random rnd = new Random();
    List<int> records = new List<int>();
    for(int i=0;i<2000000;i++)
    {
        records.Add(rnd.Next());
    }

    Action action1 = () =>
    {
        var res1 = records.GroupBy(r => r % 2)
                    .OrderBy(x => x.Key)
                    .Select(x => x.OrderBy(y => y))
                    .SelectMany(x => x)
                    .ToList();
    };

    Action action2 = () =>
    {
        var res2 = records.OrderBy(x => x % 2).ThenBy(x => x).ToList();
    };


    //Avoid counting JIT
    action1();
    action2();


    var sw = Stopwatch.StartNew();
    action1();
    long t1 = sw.ElapsedMilliseconds;

    sw.Restart();
    action2();
    long t2 = sw.ElapsedMilliseconds;

    Console.WriteLine(t1 + " " + t2);
}
于 2013-02-15T18:25:08.457 回答