【发布时间】:2011-01-16 13:41:43
【问题描述】:
我需要检查特定字符串是否包含在其他字符串中:
private bool Contains(string field)
{
return this.Fields.Contains(field); // HashSet<string> local property
}
如果只有一项任务,最好使用哪种容器类型 - 保存多个字符串并检查另一个字符串是否进入?
【问题讨论】:
我需要检查特定字符串是否包含在其他字符串中:
private bool Contains(string field)
{
return this.Fields.Contains(field); // HashSet<string> local property
}
如果只有一项任务,最好使用哪种容器类型 - 保存多个字符串并检查另一个字符串是否进入?
【问题讨论】:
HashSet 有效吗?当然。但这不是你问的问题。您要求尽可能快的查找。
这是最快的吗?不,当然不是,无论如何都不是。
首先,为了谈论“最快”,我们需要准确描述“最快”的含义。你的意思是:
?请准确说明“尽可能快”的含义。只有当我们确切地知道最快对您意味着什么时,我们才能为您设计一个理论上最快的算法。
例如,假设您正在编写一个编译器。在编译器中我们必须一直做的事情是检查特定字符串是否在字符串列表中。也许我们正在检查字符串是否是关键字,因此我们必须查找给定字符串是否在集合内 {"int", "double", "for", "foreach", "class" ... }
我们可以将它们放入哈希集中并获得不错的性能。但如果我们想要可能的最佳性能,我们可以做得更好。例如,我们可以对数十亿行现有源代码进行分析,找出哪些关键字最常见,哪些最不常见,然后编写一个自定义哈希表,针对 (1) 快速拒绝根本不是关键字,并且 (2) 以识别其他关键字为代价快速识别最常见的关键字。
注意,这需要静态分析;尽管它在典型情况下表现良好,但在使用大量稀有关键字的罕见情况下表现不佳。我们可以采取的另一种方法是编写一个自我调整哈希表,该哈希表动态识别特定字符串何时被频繁搜索。
考虑一下,例如,如果您正在编写 JScript 运行时的实现。我们经常必须在一组字符串中寻找一个字符串:
for(i = 0; i < 10; ++i) { foo.bar(i); }
这里我们必须在“foo”标识的对象中查找字符串“bar”十次。 “foo”中实现该查找的哈希表在循环中第一次注意到“bar”已被使用,因此它动态调整哈希表结构,以便 second 时间通过循环,查找速度更快。这是我们在实现 JScript 时采用的策略。
现在,这优化了 for 循环的情况,但它使这种情况可能比它可能的慢:
for(i = 0; i < 10; ++i) { foo.bar(i); foo.blah(i); foo.abc(i); }
因为我们没有做更多的分析并意识到“嘿,我们只是重新优化了这个哈希表 3 次,现在我们要重新做一遍,也许我们应该保持原样。”
幸运的是,我们没有像您一样寻找最快的查找。我们只是在寻找相当快的查找。
您能否仔细而完整地描述最快查找的具体使用案例?您可以使用许多算法来加快查找速度,但它们变得非常复杂。
【讨论】:
是的,HashSet 非常适合这一点,因为它包含一个要查找的值,不像字典需要一个键和一个值。
【讨论】: