2009-06-29 6 views
1

タイトルが意味をなすことを願っています。コレクションのサブコレクション(ブール値ではないLINQ)でのブールANDストリング検索の実行

は、私が検索し、すべてが少なくとも一度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

あなたは、.NET 2.0でLINQのサポートを得ると、次のLINQクエリを使用するLINQ Bridgeを使用することができます。

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

あなたは2つの内部ループを交換する場合に設定ビットの使用を避けることができます - パフォーマンスへの影響は、キーワードの数対のサブアイテムの数に依存します。

+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

完全一致が許可されている場合は、より良い最適化が利用可能になります。たとえば、O(1)ルックアップ時間を与えるキーワードを辞書にキーとして格納する(または、後のバージョンの.NETでHashSetを使用する)ことができます。 – LukeH

+0

ルーク、はい、間違いだったのは、==の代わりに.Contains()でした。それをキャッチするためにありがとう!私はコードを編集しました。しかし、私は辞書/ハッシュの使用に関するあなたの評価に同意しません。ハッシュルックアップはO(1)であることを理解していますが、この状況でパフォーマンスを向上させるために直接適用できる方法はわかりません。コードサンプルを提供してください。コメントありがとう。 – dss539

関連する問題