2010-07-28 4 views
3

일반 List이 있는데이 목록에서 특정 문자열을 찾아야합니다. 아래에서 최선의 접근법을 알려주십시오.일반 목록의 항목을 검색 할 때 LINQ 또는 포함을 사용해야합니까?

if (strlist.Contains("Test")) 
{ 
    // String found 
} 

또는

string res = (from d in strlist where d == "Test" select d).SingleOrDefault(); 

if (res == "Test") 
{ 
    //found 
} 

데이터베이스에서 인구가 매우 큰 수 있습니다 목록을 고려하시기 바랍니다

. 이것에 대한 여러분의 생각은 높이 평가됩니다.

+2

필수 : ​​테스트를 마쳤습니까? – ChaosPandion

답변

5

List<string> (또는 IEnumerable<string>)이 있고 Contains가 필요 사항을 충족하는 경우 포함을 사용하십시오.

는 제공하지 않습니다 포함 몇 가지 추가 처리를해야하는 경우, 내가 사용 제안 모든() :

두 가지 방법이 하나 개 이상 일치하는 경우 다르게 동작합니다
if(strList.Any(s => s.StartsWith("Tes")) 
{ 
    // Found 
} 
+1

Exacaly, 컴파일러는 어쨌든 최적화 기능을 제공하며 Contains가 포함 된 스 니펫은 훨씬 좋아 보인다.) –

2

; 첫 번째 것은 true를 반환하고 두 번째 것은 예외를 throw합니다.

이를 수정하려면 SingleOrDefaultFirstOrDefault으로 변경하십시오.

정확히 일치하는 항목을 검색하는 경우 Contains을, 그렇지 않은 경우 Any으로 전화해야합니다. 예를 들어

: 당신은 정말 Contains의 성능으로 HashSet<string>를 사용해야합니다

if (strings.Contains("SomeString", StringComparer.OrdinalIgnoreCase)) 

if (strings.Any(s => s.StartsWith("b")) 
+0

사실 두 번째는 그렇지 않습니다. 당신은 '싱글'을 생각하고 있습니다. – ChaosPandion

+0

@ChaosPandion : 틀렸어. 'SingleOrDefault'는 _zero_와 일치하는 경우에만'default (T)'를 반환합니다. 그렇지 않으면'FirstOrDefault'와 동일합니다. – SLaks

+0

나는 당신이 정말로 텍스트에서 감성적 인 의도를 읽지 말아야한다는 것을 알고 있지만 아프다. – ChaosPandion

0

극적으로 좋습니다. 이제 다른 작업에 대한 목록을 사용해야하는 경우 두 가지를 모두 사용할 수 있습니다.

var list = BuildListOfStrings(); 
var set = new HashSet<string>(list); 

if (set.Contains("Test")) 
{ 
    // ... 
} 

이제 세트의 항목을 O(1) 조작으로 찾을 수 있습니다.

테스트

static void Main(string[] args) 
{ 
    var lst = GenerateStrings().Take(5000000).ToList(); 
    var hsh = new HashSet<string>(lst); 
    var found = false; 
    var count = 100; 
    var sw = Stopwatch.StartNew(); 

    for (int i = 0; i < count; i++) 
    { 
     hsh = new HashSet<string>(lst); 
    } 
    Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks/count)); 

    sw = Stopwatch.StartNew(); 
    for (int i = 0; i < count; i++) 
    { 
     found = lst.Contains("12345678"); 
    } 
    Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks/count)); 

    sw = Stopwatch.StartNew(); 
    for (int i = 0; i < count; i++) 
    { 
     found = hsh.Contains("12345678"); 
    } 
    Console.WriteLine(TimeSpan.FromTicks(sw.ElapsedTicks/count)); 

    Console.WriteLine(found); 
    Console.ReadLine(); 
} 

private static IEnumerable<string> GenerateStrings() 
{ 
    var rnd = new Random(); 
    while (true) 
    { 
     yield return rnd.Next().ToString(); 
    } 
} 

결과

 
0.308438 s 
0.0197868 s 
0.0 s 

은 그래서 이것은 우리에게 무엇입니까? Contains으로 소량의 전화를 걸려면 List<string>을 사용하고, 그렇지 않으면 HashSet<string>을 사용하십시오.

+1

주문을 보존해야 할 경우에는하지 말아야합니다. – SLaks

+0

@SLaks - 분명히 맞지만 목록이 매우 클 수 있다는 사실은 이것이 성능을 획기적으로 향상 시킨다는 것을 의미합니다.'string'은 참조 타입이므로 다른 연산을 위해서'List '을 간단하게 유지할 수 있으며 과도한 메모리 사용에 대해 걱정할 필요가 없습니다. – ChaosPandion

+1

이것은 목록의 포함이 고정되어 있고이 작업이 반복적으로 수행된다고 가정합니다. 하나의 Contain를 수행하기 위해 ad hoc hashSet을 작성하면 List에 Contains가 포함 된 호출이 느려질 것입니다. –

관련 문제