If the elements in the array are unique and you need many (or all) of them, a simple approach is: 1) shuffle the array, 2) pick first n
elements.
If you don't need many of them shuffling the whole array is overkilling and picking can instead be intermixed with the shuffling:
function randomOrder(L) {
let data = L.slice(), count = L.length;
return function() {
if (count === 0) throw Error("No more values available");
let j = Math.floor(Math.random()*count);
let value = L[j];
L[j] = L[--count];
return value;
};
}
If elements are not unique you must also do a check that the same value was not used before; depending on the size of the array and on how many elements you want to extract it could make sense to use a Set
object to track them:
function randomOrderDistinct(L) {
let data = L.slice(), count = L.length, used = new Set;
return function() {
for(;;) {
if (count === 0) throw Error("No more values available");
let j = Math.floor(Math.random()*count);
let value = L[j];
L[j] = L[--count];
if (!used.has(value)) {
used.add(value);
return value;
}
}
};
}