【问题标题】:Is there a way to search a Dictionary in multiple ways using key searching?有没有办法使用键搜索以多种方式搜索字典?
【发布时间】:2011-10-15 05:12:27
【问题描述】:

基本上我有一个Dictionary<Guid, Movie> Movies 集合并使用Guid 搜索电影,它基本上是movie.Guid。它很好用,但我也希望能够使用 movie.Name 搜索同一个字典,而无需遍历每个元素。

这可能吗,还是我必须为此创建另一个Dictionary<K, V>

【问题讨论】:

  • 您希望将来搜索其他字段吗?
  • 如果您从数据库中填充字典,那么您最好在数据库查询中进行过滤。
  • 您是要进行精确 名称匹配,还是希望能够搜索部分名称匹配?似乎不太可能有人会搜索“终结者 3:机器的崛起”。另外,为什么使用 GUID 作为唯一标识符而不是通用产品代码或其他专门用于媒体的标准标识符?
  • 你为什么关心 Mem 的性能。数据?你有多少条目? 100M? 1G?
  • @Joan 那种。寻找 en.wikipedia.org/wiki/SQL_Server_Compact - 它似乎(我不是 C# 人,我是 Java 人)在轻量级数据库中拥有您正在寻找的一切。

标签: c# .net dictionary


【解决方案1】:

只有两个字典,其中一个以 guid 作为键,另一个以名称作为键。

【讨论】:

    【解决方案2】:

    如果您不想查看每个元素,则需要将其索引到另一个方向。这意味着另一个字典得到 O(1)

    【讨论】:

    • 谢谢,你指的另一个方向是什么意思?
    • 为了在 O(N) 中进行查找,您需要一个“索引”,在这种情况下,它是通过字典完成的。 “在另一个方向”这个短语是一个糟糕的描述方式。
    【解决方案3】:

    您可以遍历变量,但随后您无法在字典中获取常量时间搜索值(因为键被散列的方式。)上面关于使用两个字典散列对您的对象的引用的答案可能是如果您没有太多要引用的对象,这是一个很好的解决方案。

    【讨论】:

      【解决方案4】:

      您可以使用 Values 属性进行搜索:

      dictionary.Values.Where(movie => movie.Name == "Some Name")
      

      您将失去基于键的查找的效率,但它仍然可以工作。

      【讨论】:

      • 谢谢,我现在就是这样做的,但我想要 O(1) :O
      【解决方案5】:

      由于字典用于 one-way 映射,因此您无法从值中获取键。

      你需要两本字典。

      还有一个建议: 您可以将自定义散列函数用于键而不是 GUID,并将 Movie Names 散列存储为键。然后,您实际上可以在字典中执行两种方式的搜索。

      【讨论】:

      • 谢谢,这是一个有趣的想法。你将如何为字符串实现哈希?使用 string.GetHashCode()?
      • 我将使用 Cryptography MD5 哈希类并使用 String.ToBase64()Text.Encoding.GetBytes() 方法进行字节 字符串转换。
      • 谢谢,这看起来很酷。使用这些会产生任何性能开销吗?
      • 我不这么认为,当你想按名称搜索一个键时,你只需要一次计算它的哈希值并在你的字典中找到那个哈希值。对于您要添加的每个项目,您应该计算电影名称哈希。
      【解决方案6】:

      与其使用两个字典,不如使用一个包含两个字典的容器类。

      某个名叫 Jon 的人提出了一个部分解决方案(您可以轻松地在此基础上进行构建),将他的代码留在这里:Getting key of value of a generic Dictionary?

      【讨论】:

      • 谢谢,但这只能通过在我的情况下提供GuidMovie 才有效,对吧?不是GuidName,而是非常有趣的想法。
      • 啊,我明白了。我以为您想通过GuidMovie 进行搜索。好吧,在那种情况下,不完全是,但我仍然会应用相同的原则:在容器类中使用它们并在那里封装你的逻辑。
      • 谢谢,这是一个有趣的想法,我可能会实施,但 BiDictionary 无论如何都很酷。
      【解决方案7】:

      您无法使用该字典以同样的效率进行搜索。但是您可以轻松地针对字典的 Values 属性运行 LINQ 查询,该属性只是 Movie 值的集合。

      var moviesIWant = From m in movieLookup.Values
                        Where m.Name == "Star Wars"
                        Select m
      

      一些想法:

      • 但当您找到答案时,您将拥有指南,除非它们也是电影的属性。
      • 对于一本小字典,这很好。对于大型和重复搜索,您应该考虑创建其他字典,键入您希望搜索的其他值。只有这样,您才能达到与原始字典相媲美的 guid 查找速度。

      您可以创建另一个以名称为键的字典。完成此操作后,您可以通过它的键来搜索该词典,即使对于非常大的词典,它也将具有与原始词典相同的超级效率。

      var moviesByName = movieLookup.Values.ToDictionary(m => m.Name, m => m)
      

      【讨论】:

      • 谢谢,就我而言,Movie 类型具有 Guid 值,因此我仍然可以从那里访问它。
      【解决方案8】:

      不,我不相信这是可能的。您将不得不使用另一本字典。

      如果您要搜索更多电影属性,最好将数据移至数据库并使用该数据库进行查询。毕竟,这就是数据库的好处。

      【讨论】:

      • 您可以在要搜索的每一列上都有一个索引,这将为您提供二进制搜索性能。
      猜你喜欢
      • 1970-01-01
      • 2017-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      • 2012-10-25
      • 1970-01-01
      相关资源
      最近更新 更多