2013-02-14 1 views
5

사용자가 IANA - Protocol Registry에서 프로토콜을 쉽게 선택할 수 있도록 서비스를 만드는 중입니다.효율적으로 제한하고 linq/lambda 식으로 결과를 연결하는 방법?

레지스트리에서 http이라는 단어를 검색하면 많은 조회수가 발생한다고 생각할 수 있습니다. amt-soap-http은 곧바로 http보다 사용자가 자주 선택하기 때문에 http으로 시작하는 모든 것을 꺼내어 나머지 결과와 연결하는 것이 좋습니다. 내가 필요한 것보다 내 결과를 통해 번 이상 반복하고 같은

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

불행하게도, 내가 느끼는 :

아래 람다 식는 사고 과정의 결과이다. 조기 최적화 고려 사항을 제외하고는 위의 것보다 더 효율적인 λ 식 조합이 있습니까?

+0

'GROUPBY + SelectMany' : 하나는'n 개의 * 로그 (N) '운영과 다른'n은 ' – I4V

+0

@ I4V 그 지식을 사용하면 [대답 D 스탠리 제공] (http://stackoverflow.com/a/14884435/61654)보다 더 효율적인 대답이 나옵니까? – ahsteele

+0

ahsteele, 나는 1 개를주었습니다.하지만 3 개의 downvotes 이후에 제거했습니다. (아직 * 테스트하지 않았기 때문에 *) – I4V

답변

5

이 두 단계의 순서로 더 효율적일 수 있습니다

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

@ L.B와 이야기하는 것이 더 좋습니다. D Stanley와 나의 코드에 대한보다 효율적인 대안이 있습니까? – ahsteele

+0

@DStanley'n = 2 ** 20 (1M)'이라고 가정하면, 당신의 해답은'1M * 20'이 될 것이지만, 두 개의 0.5M 항목을 정렬하는 것은'(0.5M * 19) * 2'가 될 것입니다. 덧붙여,'ThenBy'도 있는데'(0.5M * 19) * 2' – I4V

+0

@ L.B와 저의 고매인데 6,800 포인트가 있습니다. :) – ahsteele

3

열심히지고 일을하려고하고 무엇을 설명하는 주석을 사용. 그래서 나는이 또 다른 대답을 게시 할 것이다. 임의의 정수 목록을 먼저 짝수 또는 홀수에 따라 숫자순으로 정렬하려는 경우 (StartsWithmod 2으로 시뮬레이트).

다음은 테스트 사례입니다. action2은 다른 답변과 같습니다.

이 코드를 실행하면 내 제안 (action1)이 두 배 빠름을 알 수 있습니다. Orderby`와`사이의 차이를 모른다 (@Bobson와 upvoter 같은) 사람들을 위해

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

그룹별로 레코드가 하나 인 경우 개별 레코드를 정렬하는 것보다 그룹을 정렬하는 것이 덜 효율적입니다. – Bobson

+0

@Bobson 그냥 사용해보십시오. ** 2 배 빠름 ** ** – I4V

+0

** 그룹당 레코드가 하나 뿐인 경우 ** : '3302 615'. 나는 당신의 코드를 가져 와서'rnd.Next()'를'i'로 대체하고'% 2' 호출을 꺼냈다. 이것은 OP 질문에 대한 더 가까운 근사치입니다. 목록의 각 값은 고유 한 값이고, 내가 시도한 점입니다. 둘 다에서 두 번째 순서 정렬을 가져 오면 결과는'2656 568'입니다. – Bobson

관련 문제