Skip to content Skip to sidebar Skip to footer

Sized Array Of Random Unique Numbers

I was wondering what was the most concise way to get an array of a certain size, of unique random numbers. I get random numbers like this: times(4, () => random(30, 95)); Howev

Solution 1:

I know this isn't "the lodash way", but it guarantees uniqueness, and allows you to use the same arguments as you were using before. It also scales better than methods that require a binary or linear search through an array, as set.has() is O(1) on average, rather than O(log(n)) or O(n).

functionuniqRandom (times, ...args) {
  const set = newSet()

  while (times > 0) {
    const rand = _.random(...args)

    if (!set.has(rand)) {
      set.add(rand)
      times--
    }
  }

  returnArray.from(set)
}
 
console.log(uniqRandom(4, 30, 33));
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

Solution 2:

Much easiear would be...

const uniqRandomNumbers  = _.sampleSize(_.range(30, 95), 4);
console.log(uniqRandomNumbers);
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

Solution 3:

I solved it using from a functional programming perspective. refillRandom is a recursive function that checks the number of items left to generate and calls itself again until the are the required number of items.

It also throws an Error when is imposible to generate the sequence, if the distance between min and max random number is greater than the required unique items. It's better to throw an Error than waiting forever.

constgenerator = (min, offset) => () =>Math.floor(Math.random() * offset + min);

constrefillRandom = (list, min, max, times) => {
  const offset = max - min,
    num = times - list.length;
  if (times > offset) {
    thrownewError("Imposible to generate it");
  }
  
  const result = _.uniq(_.times(num, generator(min,offset)));
  if (result.length < num) {
    return result.concat(
      refillRandom(list, min, max, num - result.length)
      );
  }
  return result;
}

const r = refillRandom([], 30, 95, 4);

console.log(r);
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

EDIT: I found another solution, I mantain an ordered array of generated numbers and increment the generated number so it get mapped to a number that has not been generated yet. This way I only call random the times specified.

constrandomGenerator = (min, offset, generated, times) => {
  if (!times || !offset) return generated;

  var number = Math.floor(Math.random() * offset + min);
  const len = generated.length;
  for (var i = 0; i < len; i++) {
    if (generated[i] <= number) {
      number++;

    } else {
      generated.splice(i, 0, number);
      returnrandomGenerator(min, offset - 1, generated, times - 1);
    }
  }
  generated[i] = number;
  returnrandomGenerator(min, offset - 1, generated, times - 1);

};


const r = randomGenerator(30, 95 - 30, [], 12);

console.log(r);
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

Post a Comment for "Sized Array Of Random Unique Numbers"