我有大量数据,在这种情况下,想象一下80,000多个String
数组都包含文件路径。
作为文件路径,它意味着它们的大组以相同的路径开始,例如我有超过50,000个文件以"/dataset1/subsetAA/childX/"
开头。
我想允许自由文本搜索这些路径。现在我用一个看起来像这样的简单谓词来做到这一点:
foreach(String term in terms)
if( path.IndexOf( term, StringComparison.OrdinalIgnoreCase ) == -1 )
return false;
return true;
我会在输入时保存搜索结果,因此您输入的内容越多,但最初的几次搜索(例如“f
”>“fo
” >“foo
”)即使在快速机器上也可能需要3到4秒。
我想构建一个子串索引,消除了我使用IndexOf
的需要,最好是利用公共路径来减少索引大小,我不想消耗太多内存。
答案 0 :(得分:2)
阅读称为Trie的数据结构:http://en.wikipedia.org/wiki/Trie
它完全符合您的要求,它需要很多字符串并使用常用前缀构建一个树,带有字符串,每个叶子都是一个字符串,它遵循其父项中的一系列前缀(您可以通过连接其所有的前缀来构建父母对叶子里的东西,以节省空间)
答案 1 :(得分:2)
然而,即使是快速的机器,最初的几次搜索(例如“f”>“fo”>“foo”)也可能需要3到4秒。
那是你唯一需要优化的东西。创建一个非常简单的结构,包含三个哈希集 - 单个字符,两个字符和三个字符。单字符哈希索引的每个元素都包含一个包含索引字符的元素列表;双字符哈希索引的每个元素都包含一个包含索引字符对的元素列表;三字符索引也是如此。
当输入搜索的初始部分时,使用索引查找。例如,在键入f
时,您将从第一个哈希表中获取包含f
的项列表。当用户继续键入时,您将从"fo"
键的第二个索引中获取项目,然后从"foo"
键的第三个索引中获取项目。
一旦你获得四个或更多字符,你就会回到基于IndexOf
的搜索,使用搜索词的最后三个字符来查找基于三个字符的哈希中的初始列表子。从列表中获得的项目数量相对较少,因此搜索速度会快得多。
另一项优化应该是在您有足够的项目显示给用户后立即停止搜索。例如,如果用户键入"tas"
(来自"dataset"
),则您的三个字符索引将为您提供50000次点击。抓住前20个(或者你需要显示的数量),并跳过其余的:用户将很快改进他们的搜索,所以不管怎样,其他项目很快就会被丢弃。