How to Efficiently Randomly Select Array Item Without Repeats

How to efficiently randomly select array item without repeats?

Whenever an item is selected, move it to the back of the array and randomly select from a slice of the original array array.slice(0, -5).

var a = ["Roger", "Russell", "Clyde", "Egbert", "Clare", "Bobbie", "Simon", "Elizabeth", "Ted", "Caroline"];

var chooseName = function () {
num = Math.floor(Math.random() * a.length - 5);
name = a.splice(num,1);
a.push(name);
}

window.addEventListener("keypress", function (e) {
var keycode = e.keyCode;
if (keycode == 13) {
chooseName();
}
}, false);

EDIT: This also has the side-effect of not giving whichever variables happen to tail the list the unfair disadvantage that they won't be considered in the first N calls. If that's a problem for you, maybe try hold a static variable somewhere to keep track of the size of the slice to use and max it out at B (in this case, 5).
e.g.

var a = ["Roger", "Russell", "Clyde", "Egbert", "Clare", "Bobbie", "Simon", "Elizabeth", "Ted", "Caroline"];
B = 5; //max size of 'cache'
N = 0;

var chooseName = function () {
num = Math.floor(Math.random() * a.length - N);
N = Math.min(N + 1, B);
name = a.splice(num,1);
a.push(name);
}

Javascript random on array without repeat

You can use a array for storing question that have been asked
Check array every time during randomization and then select question

var track=new Array();

while(true)//loop until Unique number
{
var randomQuiz=Math.floor(Math.random()*quiz.length);

if(track.indexOf(randomQuiz)==-1)//if you have got your unique random number
{
track.push(random);
break;
}
}

Edit: as Stephen P pointed out it may lead to performance issue, removing element from array is more logical thing to do as suggested by Brent Waggoner.

How to randomly select array item without repeats and not have the program ask a question twice?

Here's a hint, ditch the switch. Have an array of objects with all the questions and answers, like:

const data: [
{ question: "Who?", answer: "Him" },
{ question: "What?", answer: "That" },
{ question: "Where?", answer: "There" }
]

Ditch the for loop, use a while loop, and reuse the logic. All you need is the random index

while ( data.length > 0 ) {
let randomIndex = Math.floor(Math.random() * data.length) + 1;

var userAnswer = prompt(data[randomIndex].question)

if (userAnswer === data[randomIndex].answer) {
alert("Correct!")
score = score + 1
} else {
alert("Sorry you are incorrect")
}
data.splice(randomIndex, 1); // remove that question and answer set
}

I need to know how to iterate through an array without repeating

You can delete each random element from run.

// program to get a random samplestrong text

function getRandomItem(arr) {
// get random index value
const randomIndex = Math.floor(Math.random() * arr.length);

// get random item
const item = arr[randomIndex];

return item;
}

let runs = ["W1", "W2/W3", "W4/W6", "W5", "W7/W8", "E1/E2", "E3/E4", "E5/RB", "SA/SB", "LT",
"LR1", "LR2", "LR3", "LR4", "LR5", "LR6", "LR7", "LR8", "Mullet Creek"
];
let mainSamplers = ["RAB", "CJ", "AMR", "ND", "RB", "ED", "SD", "MEF"];
let secondarySamplers = ["KD", "SA", "AF", "JT", "EV"];

console.log("Run" + " " + "Samplers");
while (runs.length) {
//1st sample set
let val = getRandomItem(runs);
const result1 = val + " " + getRandomItem(mainSamplers) + " " +
getRandomItem(secondarySamplers);

console.log(result1);

runs.splice(runs.indexOf(val), 1);
}

How can I make a random array with no repeats?

There are two ways you could achieve this.

  1. Store an array of values already spun. Then, when you generate a new number, check if it's in the array of spun numbers. If it is, generate a new number and check again, until you get a number which isn't in the array. Otherwise, add it to the array.

  2. Generate an array of all the valid numbers up front, as you are doing. Then, every time you spin a number, remove it from that array. That way, the next time you 'spin' you will be only selecting from values which haven't been spun already.

  3. Generate an array of all the valid numbers up front, and then sort it randomly. Then all you have to do is keep taking the first item in the array.

In order, Option 3. is the most elegant, but it has the downside that someone with a console open could potentially see exactly what number is coming next! Option 2 is the next best, and if the user is allowed to know that a number can't come up twice, they can't 'cheat' by seeing the remaining available numbers. Option 1 is the least efficient - because it means your code will need to do more and more work to try and find a 'free' number.

Honestly, if your game needs to be at all secure from hacking, then you would not want to generate any random numbers client side anyway, so if this is just for a bit of fun, it won't really matter which method you use. If you are writing it for a gambling website, first let me know which one so I can make a fortune, and then move your logic to the server.

So here is an example of Option 2. approach

<!DOCTYPE html>
<html>
<head>
<script>

var numbers = []; // this array will store the available numbers..

function generateNumbers()
{
// populate the available numbers however you need to..
for(var i=0; i<360; i+=30)
{
numbers.push(i);
}
}

function spin()
{
if(numbers.length==0)
{
// then we've used up all available numbers..start new game or whatever you need to do..
alert("starting again");
generateNumbers();
}
var rand = Math.floor(Math.random()*numbers.length); // select an index randomly based on the number of remaining available numbers..
var num = numbers[rand];
numbers.splice(rand,1); // remove the number we selected so it can't be selected next time..
document.getElementById("number").innerHTML = num;
}

</script>
</head>
<body>
<button onclick="spin()">SPIN</button>
<div id="number"></div>
</body>
</html>

And Option 3. below. The main difference is that you can just shift() the next value instead of having to select randomly.

<!DOCTYPE html>
<html>
<head>
<script>

var numbers = [];

function generateNumbers()
{
for(var i=0; i<360; i+=30)
{
numbers.push(i);
}
function sort(a,b)
{
return (Math.random()>0.5)? -1 : 1;
}
numbers.sort(sort);
}

function spin()
{
if(numbers.length==0)
{
alert("starting again");
generateNumbers();
}
var num = numbers.shift();
document.getElementById("available").innerHTML = "Available:" + numbers.join(",");
document.getElementById("number").innerHTML = "Selected:" + num;
}

</script>
</head>
<body>
<button onclick="spin()">SPIN</button>
<div id="available"></div>
<div id="number"></div>
</body>
</html>

Hopefully that gives you an idea of how you could incorporate this into your code.

How to get a number of random elements from an array?

Try this non-destructive (and fast) function:

function getRandom(arr, n) {
var result = new Array(n),
len = arr.length,
taken = new Array(len);
if (n > len)
throw new RangeError("getRandom: more elements taken than available");
while (n--) {
var x = Math.floor(Math.random() * len);
result[n] = arr[x in taken ? taken[x] : x];
taken[x] = --len in taken ? taken[len] : len;
}
return result;
}

Javascript random generator with no repeats till all items have been displayed

If you don't want to alter your original array by shuffling it, you can store the unused items in a separate array and then reset it when you're out. See the comments:

var oddnumber = [
'111',
'222',
'333',
'444',
'555',
]
var oddletter = [
'AAA',
'BBB',
'CCC',
'DDD',
'EEE',
]

// to store unused items
var unused_letters = [];
var unused_numbers = [];

function newThing() {
if (numberCheck.checked) {
// if there are no unused items, copy them form the source array
if (!unused_numbers.length) unused_numbers = [...oddnumber];
var randomY = unused_numbers;
}
if (letterCheck.checked) {
// if there are no unused items, copy them form the source array
if (!unused_letters.length) unused_letters = [...oddletter];
var randomY = unused_letters;
}
var randomX = Math.floor(Math.random() * (randomY.length));

var y = randomY;
var x = randomX;
document.getElementById("thingDisplay").innerHTML = y[x];

// remove randomx from the unused array since it's been used now
randomY.splice(randomX, 1);
}
<body>
<div id='thingDisplay'></div>
<div>
<button class="box" id="button01" onclick="newThing()">New Thing</button>
</div>
<div>
<form>
Number<label> <input type="radio" name="thing" id="numberCheck"/></label>
<br/>Letter<label> <input type="radio" name="thing" id="letterCheck"/></label>
</form>
</div>
</body>


Related Topics



Leave a reply



Submit