How to make 4 variables always take different values from an array?

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.

Answer

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;