2009-06-29 88 views
1

我希望標題有意義。對集合的子集合(非LINQ)執行布爾AND字符串搜索

我有一組items,我想搜索和選擇的一個子集,基於一組的keywords必須全部出現在任何Item S的SubItems至少一次。我相信這可以很容易地使用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

多少可以子項目的項目有哪些?內部循環(對於int i = 0)對我來說看起來像一個問題。 – shahkalpesh 2009-06-29 16:23:41

+0

如果您提供樣本輸入/預期輸出將會更好。 – shahkalpesh 2009-06-29 16:25:11

回答

3

您可以使用LINQ Bridge獲得對.NET 2.0的LINQ支持並使用以下LINQ查詢。

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

如果換成兩個內環可避免使用位設置 - 性能影響取決於數量寫子項目VS關鍵字的數量。

foreach (Item item in items) 
{ 
    Boolean found = false; 

    foreach (String keyword in keywords) 
    { 
     found = false; 

     foreach (SubItem subItem in item.SubItems) 
     { 
      if (subItem.StringValue.Contains(keyword)) 
      { 
       found = true; 
       break; 
      } 
     } 

     if (!found) 
     { 
      break; 
     } 
    } 

    if (found) 
    { 
     result.Add(item); 
    } 
} 
+0

啊,當然=)謝謝! – Blixt 2009-06-30 06:21:28

0

我會寫它如下。當然這與丹尼爾的解決方案非常相似,但我相信它更好。

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

編輯:改變==.Contains()按照評論