How to effectively limit and then concatenate a result using the linq / lambda expression?

I am creating a service so that a user can select a protocol from the IANA-Protocol Registry .

As you can imagine, a registry search for a term httpcauses a lot of hits. Since the amt-soap-httpuser is going to select much less often than the direct one http, I decided that it would be nice to pull out everything that starts with http, and then combine this with the rest of the results.

The following lambda expression is the result of this thought process:

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);

Unfortunately, it seems to me that I repeat the results more often than necessary. Premature optimization considerations include a combination of lambda expressions that would be more efficient than higher?

+5
source share
2 answers

This may be more effective as a two-step ordering:

var results = records.OrderBy(r => r.Name.StartsWith(term) ? 1 : 2)
                     .ThenBy(r => r.Name)
                     .Take(MaxResultSize);
+5
source

Using a comment to explain what I'm trying to do is getting complicated. So I will send another answer. Suppose I want to sort a list of random integers first, according to whether it is even or odd, and then in numerical order (imitation StartsWithwith mod 2).

Here is a test case: action2 is the same as another answer.

If you run this code, you will see that my suggestion ( action1) is twice as fast.

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);
}
+3
source

All Articles