2009-06-29 4 views
1

제목이 의미가 있기를 바랍니다.컬렉션의 하위 컬렉션에서 부울 AND 문자열 검색 수행 (비 LINQ)

는 내가 검색하고 모두가 적어도 한 번 Item의의 SubItems의에서 나타나야합니다 keywords의 집합을 기반으로의 부분 집합을 선택합니다 items의 집합을 가지고있다. 이 쉽게 LINQ를 사용하여 얻을 수 있다고 생각하지만이 프로젝트에 .NET 2.0을 사용하고 있습니다.

아래 코드는 AllBitsAreSet이 구현되었다고 가정하고 내가하고 싶은 것을 거의 달성해야합니다. 그러나이 대안을 사용하지 않는 간단한 방법이 궁금합니다.

BitArray의 모든 비트가 설정되어 있는지 확인하는 좋은 방법이 아닌 것 같기 때문에 모두를 반복하면서 (제발 저에게 말해주세요!), "좋네요" 대안. 필자는 아래 코드가 내가 사용하고있는 데이터 세트에 비해 너무 느리다는 것을 의심 할 여지가 없으므로 더 효율적인 CPU는 아닐 것이다.

public List<Item> Search(Item[] items, List<string> keywords) 
{ 
    List<Item> results = new List<Item>(); 

    BitArray flags = new BitArray(keywords.Count); 
    foreach (Item item in items) 
    { 
     flags.SetAll(false); 
     foreach (SubItem subItem in item.SubItems) 
     { 
      for (int i = 0; i < keywords.Count; i++) 
      { 
       if (subItem.StringValue.IndexOf(keywords[i]) >= 0) 
        flags[i] = true; 
      } 
     } 
     if (AllBitsAreSet(flags)) results.Add(item); 
    } 

    return results; 
} 
+0

에 따라 .Contains()==을 변경? 내부 루프 (int i = 0의 경우)는 나에게 문제가된다. – shahkalpesh

+0

샘플 입력/예상 출력을 제공하면 더 좋을 것입니다. – shahkalpesh

답변

3

LINQ Bridge을 사용하면 .NET 2.0에서 LINQ 지원을 받고 다음 LINQ 쿼리를 사용할 수 있습니다.

items.Where(i => 
    keywords.All(k => 
     i.SubItems.Any(s => 
      s.StringValue.Contains(k)))); 

당신이 두 개의 내부 루프를 교체하는 경우 사용자가 설정 한 비트를 사용하여 피할 수 - 성능에 미치는 영향은 키워드의 수 대 하위 항목의 thenumber에 따라 달라집니다.

+0

아, 물론 =) 고마워! – Blixt

0

다음과 같이 작성합니다. 물론 이것은 Daniel의 솔루션과 매우 유사하지만 더 좋다고 생각합니다.

public List<Item> Search(Item[] items, List<string> keywords) 
    { 
     List<Item> results = new List<Item>(); 
     foreach (Item item in items) 
      if(ContainsAllKeywords(item, keywords)) 
       results.Add(item); 
     return results; 
    } 

    bool ContainsAllKeywords(Item item, List<string> keywords) 
    { 
     foreach (string keyword in keywords) 
      if (!ContainsKey(item.SubItems, keyword)) 
       return false; 
     return true; 
    } 

    bool ContainsKey(IEnumerable<SubItem> subItems, string key) 
    { 
     foreach (SubItem subItem in subItems) 
      if (subItem.StringValue.Contains(key)) 
       return true; 
     return false; 
    } 

편집 :이 항목이 얼마나 많은 하위 항목을 가질 수 있습니다 코멘트

+0

코드에는 Blixt 및 Daniel 's와 동일한 기능이 없습니다. 코드에서 subItem.StringValue와 각 키워드가 정확히 일치하는지 확인합니다. 하위 문자열 일치를 확인해야합니다. – LukeH

+0

정확한 일치가 허용되면 훨씬 더 나은 최적화가 가능합니다. 예를 들어 키워드를 Dictionary에 키로 저장하거나 O (1) 조회 시간을 제공하는 .NET의 이후 버전에서 HashSet을 사용할 수 있습니다. – LukeH

+0

루크, 그렇습니다. == 대신에 .Contains()가 있어야합니다. 그것을 잡아 주셔서 감사합니다! 코드를 편집했습니다. 그러나 사전/해시 사용에 대한 귀하의 평가에 동의하지 않습니다. 나는 해시 조회가 O (1) 인 것을 알고 있지만,이 상황에서 성능을 향상시키기 위해 어떻게 직접 적용 할 수 있는지는 알 수 없다. 코드 샘플을 제공해 주시겠습니까? 의견에 감사드립니다. – dss539

관련 문제