À mon avis, je ne pense pas que mélanger tout le jeu soit nécessaire. Vous devez juste vous assurer que votre échantillon est aléatoire et non votre jeu de cartes. Ce que vous pouvez faire, c'est sélectionner la quantité de size
depuis l'avant, puis échanger chacun des éléments dans le tableau d'échantillonnage avec une autre position. Ainsi, si vous autorisez le remplacement, vous obtenez de plus en plus mélangé.
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);
}
Cet algorithme comporte seulement 2*size
étapes, si vous incluez la méthode slice
, pour sélectionner l'échantillon aléatoire.
Plus aléatoire
Pour rendre l'échantillon plus aléatoire, nous pouvons sélectionner aléatoirement le point de départ de l'échantillon. Mais cela coûte un peu plus cher pour obtenir l'échantillon.
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;
}
Ce qui rend cela plus aléatoire, c'est le fait que lorsque vous mélangez toujours juste les éléments de tête, vous avez tendance à ne pas les obtenir très souvent dans l'échantillon si le tableau d'échantillonnage est grand et l'échantillon est petit. Ce ne serait pas un problème si le tableau n'était pas censé être toujours le même. Ainsi, cette méthode modifie la position où commence la région mélangée.
Pas de remplacement
Pour ne pas avoir à copier le tableau d'échantillonnage et ne pas se soucier du remplacement, vous pouvez faire ce qui suit mais cela vous donne 3*size
contre 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);
// Remettre tout en place.
i = size;
while(i--) {
var pop = swaps.pop();
temp = array[pop.from];
array[pop.from] = array[pop.to];
array[pop.to] = temp;
}
return sample;
}
Sans remplacement et plus aléatoire
Pour appliquer l'algorithme qui a donné des échantillons un peu plus aléatoires à la fonction sans remplacement :
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));
// Remettre tout en place.
i = size;
while(i--) {
var pop = swaps.pop();
temp = array[pop.from];
array[pop.from] = array[pop.to];
array[pop.to] = temp;
}
return sample;
}
Plus rapide...
Comme tous les articles de cette publication, cela utilise le mélange de Fisher-Yates. Mais j'ai supprimé le surplis de copie du tableau.
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 = [];