Go:没有哈希表(又名地图)的高效字符串查找?

时间:2014-08-04 18:44:45

标签: go b-tree

我在Golang中遇到问题,我需要能够查找大约5,000,000个字符串的字符串键,每个字符串只包含a-z(小写)和0-9个字符。与uint32和uint64类似的问题作为键。

地图(哈希表)非常适合这种情况,但它使用的内存太多了。

对于这类事情必须有已知的方法,我一直在研究B-Tree,但我不确定它是否是最有效的机制。

我的问题的一些特殊性可以导致更有效的解决方案:

  1. 键只需要是a-z0-9或简单uint值的字符串。
  2. 一旦构建,它只需要是只读的。
  3. 因为它只需要只读,所以在我看来,将它作为带有一系列索引的预排序列表,可能会很好。我一开始以为我可能只能在每个级别(即字符)中使用36(26个字母+10个数字)索引进行切片...但当然这意味着36 ^无论哪个最终与...相反高效。然后我想也许我可以为每个级别只放一个36的索引,但最后我需要交叉加载数组/切片以获得结果的ID。

    我想我正在寻找某种非常具体的B-Tree实现,但更多地关注我的目的(没有B。)

    有人知道我建议存在的任何事情吗?

4 个答案:

答案 0 :(得分:1)

我试试Compressed Trie。这是在具有词典键的场景中完全可用的数据结构。 B树主要用于外部记忆,因为它们最小化树的深度。特里或更高效的内存散列是正确的方法。

答案 1 :(得分:1)

我认为这取决于你想要最终实现的目标。例如:

  1. 你想(a)查找与字符串相关的一些值(例如索引或缓存)或(b)简单地测试字符串是否是一组字符串的成员(例如排除列表)? / LI>
  2. 查找的准确程度是多少 - 你能忍受误报吗?
  3. 如果问题1的答案是(a)那么trie可能是数据结构的一个很好的选择。如果问题1的答案是(b)那么你可能最好使用bitset或bloom过滤器。在这两个中,布隆过滤器将是最快和最大的内存效率,但是是概率性的,并且会产生一些误报(但没有真正的否定),根据您对问题2的回答,这可能适用于您的用例,也可能不适用。 / p>

答案 2 :(得分:0)

如果您知道要使用多少个字符串并且只需要检查它们的存在,那么优化地图和内存使用的另一个想法。

  1. 使用map[string]struct{}struct{}保证大小为0,与使用至少1个字节的bool不同。
  2. 预分配地图:m:= make(map [string] struct {},5000000)
  3. 检查if _, ok := m[key]; ok { ... }
  4. 是否存在密钥

    Compressed Tries很好,但是除非你非常紧迫地记忆,map[string]struct{}会更快。

答案 3 :(得分:0)

您应该使用Trie数据结构,该结构旨在非常有效地将字符串映射到值。有关详细信息,请参阅https://en.wikipedia.org/wiki/Trie

https://github.com/alphagov/router/tree/master/trie

上可以找到作为英国政府新网站一部分的大量使用的Go。