4
\$\begingroup\$

Is there a better way of generating a series of unique and random integers between 1 and 10 in JavaScript (ES6)?

const ran = [];

while (ran.length < 10) {
  x = Math.floor((Math.random() * 10) + 1);
  if (!ran.includes(x)) {
    ran.push(x);
  }
}
console.log(ran);
\$\endgroup\$
4
\$\begingroup\$

Your code could potentially run forever - in theory, it could randomly pick the same number again and again and again. Probably won't, but the point is that the code may take a long time to run.

A simpler approach is to generate the numbers 1-10, and then shuffle them, Fisher-Yates style. Something like:

var numbers = new Array(10),
    shuffled = [];

// fill one array with the numbers 1-10
numbers = numbers.fill(1).map((_, i) => i + 1);

// shuffle by taking a random element from one array
// and pushing it to the other array
while (numbers.length) {
  let idx = numbers.length * Math.random() | 0; // floor trick
  shuffled.push(numbers[idx]);
  numbers.splice(idx, 1);
}

console.log(shuffled);

(The "floor trick" works by using bitwise OR. Now, bitwise OR zero does actually do anything, but all JavaScript bitwise operations interpret their operands to 32-bit integers, so it's like casting to an int, discarding decimals - i.e. it floors the number.)

\$\endgroup\$
  • 1
    \$\begingroup\$ It's probably worth noting that in both your solution and mine, it's required to use double the memory, because of the initial array, while the original code only uses one array. Not a problem with 10 numbers, but with large data it may be an issue. \$\endgroup\$ – ChatterOne Jan 20 '17 at 10:35
  • 1
    \$\begingroup\$ @ChatterOne I don't know if it'll impact memory much - depends on the runtime, I'd imagine. As one array grows, the other shrinks, so really it's using a fixed amount of memory; the overhead for a 2nd array is negligible. Anyway, for getting very large amounts of non-repeating numbers, a linear feedback shift register would be a better solution anyway. \$\endgroup\$ – Flambino Jan 20 '17 at 12:44
2
\$\begingroup\$

@Flambino beat me to it, but here's a similar solution, just styled it differently:

var sorted = Array.apply(null, {length: 10}).map(Number.call, Number);
var shuffled = [];

while (sorted.length > 0) {
  shuffled.push(sorted.splice(Math.floor(Math.random()*sorted.length), 1)[0]+1);
}

console.log(shuffled);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.