测试一个值是否包含在Dictionary <tkey,list <tvalue =“”>&gt; </tkey,>中

时间:2009-12-31 18:12:29

标签: c# linq .net-3.5 linq-to-entities

我需要确定List中包含的任何Dictionary是否包含指定的值。我是LINQ的新手,以下是实现这一目标的正确方法吗?

Dictionary lotsOfStuff = new Dictionary<string, List<string>>();
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 个答案:

答案 0 :(得分:3)

此代码有效并且尽可能高效。因为您正在搜索值,所以没有索引/哈希来指导搜索。因此,您必须搜索所有对象以确定值是否存在。

答案 1 :(得分:3)

您的代码可以正常运行,但有两件事情会立即浮现在脑海中。首先,如果字典很大或值列表很大,它会很慢。我想到的第二件事是你试图进行这种搜索,这告诉我你已经把字典倒在了一起。如果你有一本字典:

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

你问的问题是“在任何价值清单中都是ABC吗?”然后你向后建了字典。您要构建的词典是

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

你应该问的问题是“ABC是字典的关键吗?”你为什么要建立字典向后

答案 2 :(得分:1)

该代码存在潜在问题。如果其中一个列表为null(即使该值存在于另一个列表中),您可能会获得NullReferenceException。要修复,请尝试:

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

答案 3 :(得分:0)

假设您想要区分大小写的匹配,您的代码将起作用,并且是最好的方法。

如果您想要不区分大小写的匹配,请传递StringComparer,如下所示:

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

顺便说一下,如果你想获得所有的值,你可以写

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

答案 4 :(得分:0)

你的linq很好,我就是这样做的

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

Eric Lippert提出了一个很好的建议。如果经常发生这种搜索,您希望使用不同的数据结构 - 特别是对此字典的值进行散列处理。以下是我将如何制作和使用它。

ILookup<string, string> 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();