На мой взгляд, я не считаю необходимым тасовать всю колоду. Вам просто нужно убедиться, что ваш образец случайный, а не ваша колода. Что вы можете сделать, так это выбрать количество size
спереди, а затем поменять местами каждое из них в массиве выборки с другой позицией в нем. Итак, если вы разрешаете замену, вы все больше и больше перемешиваете.
function getRandom(length) { return Math.floor(Math.random()*(length)); }
function getRandomSample(array, size) {
var length = array.length;
for(var i = size; i--;) {
var index = getRandom(length);
var temp = array[index];
array[index] = array[i];
array[i] = temp;
}
return array.slice(0, size);
}
Этот алгоритм состоит всего из 2*size
шагов, если вы включите метод slice
для выбора случайной выборки.
Больше случайных
Чтобы сделать выборку более случайной, мы можем случайным образом выбрать начальную точку выборки. Но это немного дороже, чтобы получить образец.
function getRandomSample(array, size) {
var length = array.length, start = getRandom(length);
for(var i = size; i--;) {
var index = (start + i)%length, rindex = getRandom(length);
var temp = array[rindex];
array[rindex] = array[index];
array[index] = temp;
}
var end = start + size, sample = array.slice(start, end);
if(end > length)
sample = sample.concat(array.slice(0, end - length));
return sample;
}
Что делает это более случайным, так это тот факт, что, когда вы всегда просто перетасовываете первые элементы, вы, как правило, не очень часто получаете их в выборке, если массив выборки велик, а выборка мала. Это не было бы проблемой, если бы массив не должен был всегда быть одним и тем же. Итак, что делает этот метод, так это изменяет эту позицию, где начинается перетасованный регион.
Нет замены
Чтобы не копировать массив выборки и не беспокоиться о замене, вы можете сделать следующее, но это даст вам 3*size
против 2*size
.
function getRandomSample(array, size) {
var length = array.length, swaps = [], i = size, temp;
while(i--) {
var rindex = getRandom(length);
temp = array[rindex];
array[rindex] = array[i];
array[i] = temp;
swaps.push({ from: i, to: rindex });
}
var sample = array.slice(0, size);
// Put everything back.
i = size;
while(i--) {
var pop = swaps.pop();
temp = array[pop.from];
array[pop.from] = array[pop.to];
array[pop.to] = temp;
}
return sample;
}
Нет замены и больше случайных
Чтобы применить алгоритм, который давал немного больше случайных выборок, к функции без замены:
function getRandomSample(array, size) {
var length = array.length, start = getRandom(length),
swaps = [], i = size, temp;
while(i--) {
var index = (start + i)%length, rindex = getRandom(length);
temp = array[rindex];
array[rindex] = array[index];
array[index] = temp;
swaps.push({ from: index, to: rindex });
}
var end = start + size, sample = array.slice(start, end);
if(end > length)
sample = sample.concat(array.slice(0, end - length));
// Put everything back.
i = size;
while(i--) {
var pop = swaps.pop();
temp = array[pop.from];
array[pop.from] = array[pop.to];
array[pop.to] = temp;
}
return sample;
}
Быстрее...
Как и во всех этих сообщениях, здесь используется перетасовка Фишера-Йейтса. Но я удалил накладные расходы на копирование массива.
function getRandomSample(array, size) {
var r, i = array.length, end = i - size, temp, swaps = getRandomSample.swaps;
while (i-- > end) {
r = getRandom(i + 1);
temp = array[r];
array[r] = array[i];
array[i] = temp;
swaps.push(i);
swaps.push(r);
}
var sample = array.slice(end);
while(size--) {
i = swaps.pop();
r = swaps.pop();
temp = array[i];
array[i] = array[r];
array[r] = temp;
}
return sample;
}
getRandomSample.swaps = [];
person
tkellehe
schedule
15.06.2016