2009-05-22 5 views
5

私は現在、これを達成するために、次のコードを使用していますが、もっと良いものがあるはず思われる...の提案?もしあれば、ディクショナリでLINQ Where句を使用する場合、同じタイプのディクショナリを返すにはどうすればよいですか?

Dictionary<string, string> GetValidIds(Dictionary<string, string> salesPersons, 
    IList<string> ids) 
{ 
    return salesPersons 
     .Where(p => ids.Contains(p.Key)) 
     .ToDictionary(p => p.Key, p => p.Value); 
} 

答えて

5

リストに物事を見ているに関する騒ぎがたくさんあるように思われます。リストにいくつかの要素しか含まれていない場合、大きな問題はありません。リストに何千もの要素が含まれている場合は、O(1)ルックアップが必要です。 HashSetはこれを提供できます。

Dictionary<string, string> getValidIds(
    Dictionary<string, string> SalesPersons, 
    List<string> ids 
) 
{ 
    HashSet<string> idsFast = new HashSet<string>(ids); 
    Dictionary<string, string> result = SalesPersons 
    .Where(kvp => idsFast.Contains(kvp.Key)) 
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value) 
    return result; 
} 
9

です辞書(長さN)の上に最初を列挙し、包含のためにリスト(長さM)をチェックし、その後、あなたはO(NM)の性能を得ることができます。

あなたはIDのHashSet<>を構築することができますが、我々はすでに利用可能(事前にハッシュされた)辞書を持っているので、それは冗長なようです。

代わりに、最初にIDを反復処理します。しかし、これはLINQを使用しないことを意味するかもしれません(TryGetValueはLINQを愛しません(そして、タプルをあまりにも多く導入するとハードワークのような)...

Dictionary<string, string> getValidIds(
      IDictionary<string, string> salesPersons, 
      IEnumerable<string> ids) { 
     var result = new Dictionary<string, string>(); 
     string value; 
     foreach (string key in ids) { 
      if (salesPersons.TryGetValue(key, out value)) { 
       result.Add(key, value); 
      } 
     } 
     return result; 
    } 

それが過度これはLINQのバージョンよりも多くの行であることを私には関係しませんが、それは複雑さのO(N)を削除...


編集する;次の(私はそれをテストしていない)の仕事かもしれないが、私はLINQの乱用だと思うし、確かにPLINQなどに拡大しないだろう...極端な注意と使用! foreachアプローチは、単純に少ないオーバーヘッドを持っているので、とにかく...速くなります。

Dictionary<string, string> getValidIds(
     IDictionary<string, string> salesPersons, 
     IEnumerable<string> ids) 
    { 
     string value = null; 
     return (from key in ids 
       where salesPersons.TryGetValue(key, out value) // HACK: v. dodgy 
       select new { key, value }) 
       .ToDictionary(x=>x.key, x=>x.value); 
    } 
+0

私はあなたがこの種のものでPERF心配している場合は、それがあるように、メモリ内あまりにも多くを持っていると思いますが、マルク、 –

+0

1 ...パフォーマンスのノートのための私の返事を参照してください! :) –

+1

@Matt ...まあ、多分 - しかし、O(1)/ O(N *ログ(N))* *は不合理ではなく、O(N^2)*はある点が、A *あり問題は、それが1k、10k、100kかどうかはもちろん、特定のプロセスまでです。 –

6

興味深いことに:ちょうど... foreachのをスキップする方法があるはず私にはあなただけのどこに呼び出しの結果にToDictionaryを呼び出すことができますかなり確信して

Dictionary<string,string> getValidIds(Dictionary<string,string> SalesPersons,List<string> ids) 
{ 
    Dictionary<string,string> o = new Dictionary<string,string>(); 
    var ie = SalesPersons.Where<KeyValuePair<string, string>>(t => ids.Contains(t.Key)); 
    foreach (var i in ie) 
    { 
     o.Add(i.Key, i.Value); 
    } 
    return o; 
} 
関連する問題