2


0

値がDictionary <TKey、List <TValue >>に含まれているかどうかのテスト

Dictionary`に含まれる List`に指定された値が含まれているかどうかを判断する必要があります。 私はLINQが初めてなので、これを達成する正しい方法は次のとおりですか?

Dictionary lotsOfStuff = new Dictionary>();
string searchString;

// populate lotsOfStuff and searchString...

// detemine if any of the values of lotsOfStuff contain searchString
bool existsInDictionary = lotsOfStuff.Values.Any(values => values.Contains(searchString));

上記が機能する場合、それをより正確にするか、より最適/簡潔にする方法はありますか?

5 Answer


3


このコードは機能し、可能な限り効率的です。 値を検索しているため、検索をガイドするインデックス/ハッシュはありません。 したがって、すべてのオブジェクトを検索して、値が存在するかどうかを判断する必要があります。


3


コードは機能しますが、すぐに2つのことが思い浮かびます。 1つ目は、辞書が大きい場合や値リストが大きい場合は遅くなることです。 2番目に思い浮かぶのは、この検索を実行しようとしているという事実が、辞書を逆方向にまとめたということです。 辞書を持っている場合:

"Frob" --> "Foo", "Bar", "Baz"
"Blob" --> "Baz", "ABC"

そして、あなたが尋ねている質問は「ABCはどの値リストにもありますか?」です。その後、逆方向に辞書を作成しました。 構築したい辞書は

"Foo" --> "Frob"
"Bar" --> "Frob"
"Baz" --> "Frob", "Blob"
"ABC" --> "Blob"

そして、あなたが尋ねるべき質問は「ABCは辞書のキーですか?」です。辞書を作成するのは_backwards_?


1


そのコードには潜在的な問題があります。 リストの1つが「null」の場合(値が別のリストに存在する場合でも)、「NullReferenceException」が発生する可能性があります。 修正するには、次を試してください:

bool existsInDictionary = lotsOfStuff.Values
             .Any(values => values != null && values.Contains(searchString));


0


大文字と小文字を区別する一致が必要であると仮定すると、コードは機能し、それを行うための最良の方法です。

大文字と小文字を区別しない一致が必要な場合は、次のように `StringComparer`を渡します。

lotsOfStuff.Values.Any(values => values.Contains(searchString, StringComparer.OrdinalIgnoreCase));

ところで、すべての値を取得する場合は、次のように記述できます。

var allValues = lotsOfStuff.Values.SelectMany(v => v);


0


あなたのlinqは大丈夫です、ここに私がそれをする方法があります

bool existsInDictionary = lotsOfStuff
  .SelectMany(kvp => kvp.Value)
  .Any(valString => valString == searchString);

'' '' '

Eric Lippertは良い提案をしました。 この種の検索が頻繁に発生する場合は、別のデータ構造、具体的にはこの辞書の値でハッシュ化されたものを使用する必要があります。 これを作成して使用する方法を次に示します。

ILookup reverseLookup =
(
  from kvp in lotsOfStuff
  from valString in kvp.Value
  select new {key = valString, value = kvp.Key}
).ToLookup(x => x.key, x => x.value);

bool existsInDictionary = reverseLookup[searchString].Any();