Javascript 该算法如何拾取随机对象密钥?(Math.random()<;1/&x2B;&x2B;c) 功能随机键(obj){ var-ret; var c=0; for(obj中的var键) if(Math.random()

Javascript 该算法如何拾取随机对象密钥?(Math.random()<;1/&x2B;&x2B;c) 功能随机键(obj){ var-ret; var c=0; for(obj中的var键) if(Math.random(),javascript,Javascript,有人能解释一下这个代码是如何公平地从对象中选择一个随机键的吗?假设您在obj中有三个键。在循环的第一次迭代中,1/++c将是1,因此ret将始终设置为第一个键。在第二次迭代中,1/++c将等于0.5,因此生成的随机数小于该值的概率为1/2,因此将ret更改为第二个键的概率为50%。在第三次迭代中,1/++c将为0.333…,因此,ret更改为第三个键的概率为1/3 对于obj中的任何大小的集合,您都应该得到均匀分布的密钥。我们可能在randomKey函数中传递一个哈希作为obj,然后我们初始化两

有人能解释一下这个代码是如何公平地从对象中选择一个随机键的吗?

假设您在
obj
中有三个键。在循环的第一次迭代中,
1/++c
将是
1
,因此
ret
将始终设置为第一个键。在第二次迭代中,
1/++c
将等于0.5,因此生成的随机数小于该值的概率为1/2,因此将
ret
更改为第二个键的概率为50%。在第三次迭代中,
1/++c
将为0.333…,因此,
ret
更改为第三个键的概率为1/3


对于
obj
中的任何大小的集合,您都应该得到均匀分布的密钥。

我们可能在randomKey函数中传递一个哈希作为obj,然后我们初始化两个变量,然后开始一个循环,检查生成的随机数是否小于1/++c,最后函数返回标记变量“ret”和“c”的retnever trust代码@deceze您将有1/20的机会在20个对象的集合中选择第20个键(或任何键)。@Bill Yes,我意识到,仍然像James一样怀疑迭代的方式是否不利于较早的键。可能只是我们的直觉背叛了我们。我倾向于把这篇文章发上去,但我害怕,无论如何我都不会理解答案@JamesThorpe这段代码看起来像是来自一个混淆的竞争。是的,我同意它的结果是均匀分布。但这种方式很奇怪。我只需要在0和Object.keys(obj).length-1之间做一个随机整数(假设你只想要自己的属性)@NicholasTower这可能是某人的工作安全性@蜥蜴比尔:从对象中获取随机密钥最简单、最有效的方法是什么?@johnaniser尼古拉斯提到的方法比使用循环更简单。上有几个实现,包括您在这里的问题中给出的实现。第二个答案是更简单的方法。
function randomKey(obj) {
    var ret;
    var c = 0;
    for (var key in obj)
        if (Math.random() < 1/++c)
           ret = key;
    return ret;
}