OCaml中哈希表的随机枚举

时间:2010-10-29 12:41:09

标签: random hashtable ocaml enumeration

4 个答案:

答案 0 :(得分:3)

我有两个建议。第一种是更改rand_enum函数,使其返回Enum.t:

let rand_enum ht n =
BatRandom.init n;
let hte = BatHashtbl.enum ht
in Array.enum (BatRandom.shuffle hte)

这并不是完全不同的(它仍然计算所有20k的随机枚举),但更接近你原来想要的。

或者,您可以随时获取HashTbl的源代码并使用rand_enum函数重新编译它。然而,这也可能不会那么不同,因为HashTbl是作为一个数组实现的,如果你想避免重复错误,你可能最终会使用shuffle。

答案 1 :(得分:2)

下一个潜在元素的密度是多少? decide功能的费用是多少?

您当前的所有解决方案都有O(n)成本。 Fisher-Yates是O(n)(尝试为Enums调整它没有多大意义,因为它无论如何都需要强制枚举),而Array.to_list alos是O(n)。

如果您的decide函数足够快且密度足够低,我认为构建所有符合条件的元素的列表/数组可能更简单(在表的每个元素上调用decide ),然后随机选择其中一个。

如果密度足够高且费用decide,我认为你的第一个想法是随机挑选密钥并保留已经遇到的密钥列表。您将能够选择遇到的第一个符合条件的元素(decide次呼叫的最佳数量)。这种枚举序列的方式“最终”成本很高,当所有元素都已被选中时,但如果密度很高,则不会遇到这种情况。

如果你不知道,从“高密度”假设开始可能会很有趣,一旦你看到桌子的某个部分,就会改变主意,但仍然没有找到。

最后:如果你不需要在生成序列期间添加/删除元素,那么将哈希表转换为数组一次并将forall(保留另一个键 - >数组索引表放在某处)会很有趣,因为当索引是连续的时,所有这些问题都会更简单。

答案 2 :(得分:2)

您的实施)(第二和第三)太复杂了。我不喜欢mutable,我不喜欢Enum。将两者结合起来是最好的方法,可以通过不受控制的副作用来拍摄脚部。

我还认为你的特定问题太具体了,不能通过看起来像通用的“随机播放的东西而且就是它”来解决。试图找到这样一个独立于域的函数,它也能解决你的特定领域问题,这也许就是为什么你的连续实现在每次尝试时变得更加丑陋和复杂。

从Hashtable生成随机流很简单:BatHashtbl.enum |- BatRandom.shuffle |- BatArray.enum。其余代码应该涉及decide函数的使用。

答案 3 :(得分:0)

我怀疑Hashtbl暴露的界面有这样的功能。将所有值放入数组并通过Array.get a (Random.int (Array.length a))进行查找的明显方法对我来说很好。