I want to make it so that each one of these four variables always takes a different "name" value taken from the array. I wanted to write it so that it check whether the variable is equal to any of the other ones, and if it is, it re-randomizes it to be different. So far I've got this:
const arr = [{name:"a"},{name:"b"},{name:"c"},{name:"d"},{name:"e"},{name:"f"}]
function myFunction()
{
let var1 = arr[Math.floor(Math.random() * arr.length)].name;
let var2 = arr[Math.floor(Math.random() * arr.length)].name;
let var3 = arr[Math.floor(Math.random() * arr.length)].name;
let var4 = arr[Math.floor(Math.random() * arr.length)].name;
while (var1 == var2 || var1 == var3 || var1 == var4)
{
var1 = arr[Math.floor(Math.random() * arr.length)].name;
}
while (var2 == var1 || var2 == var3 || var2 == var4)
{
var2 = arr[Math.floor(Math.random() * arr.length)].name;
}
while (var3 == var2 || var3 == var1 || var3 == var4)
{
var3 = arr[Math.floor(Math.random() * arr.length)].name;
}
while (var4 == var2 || var4 == var3 || var4 == var1)
{
var4 = arr[Math.floor(Math.random() * arr.length)].name;
}
}
But it not only doesn't work, I've also go a problem where the variables can still be equal, because while the first "while" randomizes them to be different from others, the next "while"'s can set another variable do be equal to it.
CodePudding user response:
Try just using one while loop, and test all the possibilities. This is not a scalable solution, but if you only need 4 unique values then this will do the job. You don't even need to init the variables, because from start they all undefined, so in the loop they will get values.
function myFunction()
{
let var1;
let var2;
let var3;
let var4;
while (var1 == var2 || var1 == var3 || var1 == var4 || var2 == var3 || var3 == var4 || var2==var4)
{
var1 = arr[Math.floor(Math.random() * arr.length)].name;
var2 = arr[Math.floor(Math.random() * arr.length)].name;
var3 = arr[Math.floor(Math.random() * arr.length)].name;
var4 = arr[Math.floor(Math.random() * arr.length)].name;
}
console.log(var1);
console.log(var2);
console.log(var3);
console.log(var4);
}
}
CodePudding user response:
One possible way is to remove the selected element from the pool of available elements.
function myFunction() {
const pool = [...arr]; // <-- make a shallow copy
const numberOfRandomsToGet = 4; // <-- number of random elements to get
const randomNames = []; // <-- store here the random names
for (let n = 0; n < numberOfRandomsToGet; n) {
let randomIndex = getRandomInt(0, pool.length - 1); // <-- generate random Index
const randomElem = pool[randomIndex]; // <-- get random element at randomIndex
if (randomElem) {
pool.splice(randomIndex, 1); // remove selected element from the "pool"
randomNames.push(randomElem.name); // add name
}
}
console.log(randomNames); // dump generated random names to console
}
Working Stackblitz
CodePudding user response:
First, randomly shuffle the array, then take the first four values from the array. This guarantees that you select four distinct elements from the array. It also scales much more easily to larger arrays or selecting more (or fewer) than four elements, and potentially performs better in edge cases.
let arr = [{name:"a"},{name:"b"},{name:"c"},{name:"d"},{name:"e"},{name:"f"}];
arr.sort((a, b) => Math.random() < 0.5);
let var1 = arr[0].name;
let var2 = arr[1].name;
let var3 = arr[2].name;
let var4 = arr[3].name;
Note that this modifies the order of elements in arr
, so perform the sort operation on a copy of that array if you need to preserve the order of arr
.
Also, while the very simple and easy-to-remember shuffle technique shown here is perfectly adequate for this very small example array, if you are shuffling a very large array you might consider well-known shuffling algorithms that perform better.
Another approach is to keep track of what indexes from the array you have randomly selected, and repeatedly generate new random indexes to avoid duplicates. This avoids modifying the arr
array, which may be important depending on your use case.
let arr = [{name:"a"},{name:"b"},{name:"c"},{name:"d"},{name:"e"},{name:"f"}];
function takeUniqueRandom(arr, indexesUsed) {
let index = -1;
while (index < 0 || indexesUsed.includes(index)) {
index = Math.floor(Math.random() * arr.length);
}
indexesUsed.push(index);
return arr[index];
}
let indexesUsed = [];
let var1 = takeUniqueRandom(arr, indexesUsed).name;
let var2 = takeUniqueRandom(arr, indexesUsed).name;
let var3 = takeUniqueRandom(arr, indexesUsed).name;
let var4 = takeUniqueRandom(arr, indexesUsed).name;