0

I got 4 Math.random generators. Each picking 1 of the X objects from the array.

  var randomItem1 = projects[Math.floor(Math.random()*projects.length)];
  var randomItem2 = projects[Math.floor(Math.random()*projects.length)];
  var randomItem3 = projects[Math.floor(Math.random()*projects.length)];
  var randomItem4 = projects[Math.floor(Math.random()*projects.length)];

How can I write a function that prevents the Math.random to generate the same number as other Math.random generator.

My guess: Creating a loop that loops through the var randomItem 1 till 4. If it finds 1 or more outputs to be the same, it will regenerate a new output for 1 or more the duplicated outputs.

Any other suggestions?

Edit: This is for a website.

Reginald1234
  • 335
  • 3
  • 13

2 Answers2

1

Thanks for the interesting problem. I always used a library for this sort of thing so it was fun figuring it out.

var projects
var randomProjects

function getRandomProjects(projects, sampleSize) {
  var projectsClone = projects.slice();
  var randomItems = [];
  while (sampleSize--) {
    randomItems.push(
      projectsClone.splice(Math.floor(Math.random()*projectsClone.length), 1)[0]
    );
  }
  return randomItems;
}

projects = ['1st project', '2nd project', '3rd project', '4th project', '5th project', '6th project'];
randomProjects = getRandomProjects(projects, 4);

randomProjects.forEach(function(randomProject) {
  console.log(randomProject);
});

The projectsClone.splice(...) deletes a random project from projectsClone and returns it as a single item in an array ([<project>]). Thus in the next iteration of the loop that value (<project>) can no longer be chosen.

However I would suggest using a library if you are using this in production code. For example losdash's _.sampleSize(projects, 4)

Oscar
  • 11
  • 3
1

Update

Removed unneeded parts like Set, for loop, and added splice(). This function will mutate the original array due to splice(). Using splice() on an array of consecutive ordered numbers (even after shuffling) guarantees a set of unique numbers.


/**
 * genRan(quantity, length)
 *
 * Need a given amount of unique random numbers.
 *
 * Given a number for how many random numbers are to be returned (@quantity) and a 
 * number that represents the range of consecutive numbers to extract the random 
 * numbers from (@length), this function will:
 *  - generate a full array of numbers with the length of @length
 *  - use shuffle() to shuffle the array to provide an array of randomly ordered numbers 
 *  - splices the first @quantity numbers of the shuffled array
 *  - returns new array of unique random numbers
 *
 * @param {Number} quantity      length of returned array.
 * @param {Number} length        length of an array of numbers. 
 * 
 * @return {Array} An array of unique random numbers.
 */


Demo

Details commented in Demo

var qty = 4
var len = 100;

function genRan(quantity, length) {
  // Ensure that quantity is never greater than length
  if (quantity > length) {
    quantity = length;
  }
  // Create an array of consecutive numbers from 1 to N
  var array = Array.from({
    length: length
  }, (value, key = 0) => key + 1);
  // Run shuffle get the returned shuffled array
  var shuffled = shuffle(array);
  // return an array of N (quantity) random numbers 
  return shuffled.splice(0, quantity);
}

console.log(genRan(qty, len));

/* shuffle utility 
|| Uses Fisher-Yates algorithm
*/
function shuffle(array) {
  var i = 0;
  var j = 0;
  var temp = null;
  for (i = array.length - 1; i > 0; i -= 1) {
    j = Math.floor(Math.random() * (i + 1))
    temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
  return array;
}
zer00ne
  • 41,936
  • 6
  • 41
  • 68