代码之家  ›  专栏  ›  技术社区  ›  Ian Kemp David Boike

测试字典中是否包含值<tkey,list<tvalue>>

  •  2
  • Ian Kemp David Boike  · 技术社区  · 14 年前

    我需要确定 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 回复  |  直到 5 年前
        1
  •  3
  •   JaredPar    14 年前

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

        2
  •  3
  •   Eric Lippert    14 年前

    您的代码可以工作,但有两件事马上就会想到。首先,如果字典很大或值列表很大,则速度会很慢。第二件事让我想到的是,你试图做这个搜索的事实告诉我你已经把字典放在一起了。如果你有字典:

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

    你要问的问题是“ABC是否在任何价值清单中?”然后你把字典倒过来了。你要建立的词典是

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

    你应该问的问题是“ABC是字典的钥匙吗?”你为什么要编字典 向后的 ?

        3
  •  1
  •   Mehrdad Afshari    14 年前

    这段代码可能有问题。如果其中一个列表是 null (即使该值存在于另一个列表中),您可能会得到 NullReferenceException . 修复,尝试:

    bool existsInDictionary = lotsOfStuff.Values
                 .Any(values => values != null && values.Contains(searchString));
    
        4
  •  0
  •   SLaks    14 年前

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

    如果需要不区分大小写的匹配,请传递 StringComparer ,像这样:

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

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

    var allValues = lotsOfStuff.Values.SelectMany(v => v);
    
        5
  •  0
  •   Jay Bazuzi Buck Hodges    14 年前

    你的Linq很好,我就这么做

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

    埃里克·利珀特有个好建议。如果这种搜索经常发生,那么您需要使用不同的数据结构,特别是对字典值进行哈希处理的数据结构。以下是我如何制作和使用它。

    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();