一尘不染

从数组中采样随机子集

javascript

在不从javascript中的数组进行替换的情况下,获取随机样本的一种干净方法是什么?所以假设有一个数组

x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]

我想随机采样5个唯一值;例如,生成一个长度为5的随机子集。要生成一个随机样本,可以执行以下操作:

x[Math.floor(Math.random()*x.length)];

但是,如果多次执行此操作,则可能会多次捕获同一项。


阅读 484

收藏
2020-05-01

共1个答案

一尘不染

我建议使用Fisher-Yates混洗混洗数组的副本并进行切片:

function getRandomSubarray(arr, size) {
    var shuffled = arr.slice(0), i = arr.length, temp, index;
    while (i--) {
        index = Math.floor((i + 1) * Math.random());
        temp = shuffled[index];
        shuffled[index] = shuffled[i];
        shuffled[i] = temp;
    }
    return shuffled.slice(0, size);
}

var x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
var fiveRandomMembers = getRandomSubarray(x, 5);

请注意,这不是获取大型数组的随机小子集的最有效方法,因为它会不必要地对整个数组进行洗牌。为了获得更好的性能,您可以执行部分​​改组:

function getRandomSubarray(arr, size) {
    var shuffled = arr.slice(0), i = arr.length, min = i - size, temp, index;
    while (i-- > min) {
        index = Math.floor((i + 1) * Math.random());
        temp = shuffled[index];
        shuffled[index] = shuffled[i];
        shuffled[i] = temp;
    }
    return shuffled.slice(min);
}
2020-05-01