4

Okay, so let's say I store some of my data like this,

var thisList = {
 "items":[
 {"name":"Item1", "image":"/img/item1", "chance":0.25},
 {"name":"Item2", "image":"/img/item2", "chance":0.25},
 {"name":"Item3", "image":"/img/item3", "chance":0.50}
 ] 
}

Now I'd like to create a function that randomly picks a item out of this list with the chances being 25% of getting [0], another 25% of getting [1] and a 50% chance of getting [2]!

Is this possible? If so, how'd I do this?

Kind regards!

asked Mar 23, 2017 at 13:36

2 Answers 2

4

You can actually play it like this, tou generate a number between 0 and 100 and then you cycle on each element and sum the chance to check if it is between the value or not:

var thisList = {
 "items":[
 {"name":"Item1", "image":"/img/item1", "chance":0.25},
 {"name":"Item2", "image":"/img/item2", "chance":0.25},
 {"name":"Item3", "image":"/img/item3", "chance":0.50}
 ] 
};
function getRandom(){
 var rnd = Math.floor(Math.random() * 100);
 console.log("The number is: " + rnd);
 var counter = 0;
 for(i=0;i<thisList.items.length;i++)
 {
 counter += thisList.items[i].chance * 100;
 if(counter > rnd){
 console.log(thisList.items[i]);
 break;
 }
 }
}
getRandom();

EDIT:

If you want to control even with a variant chance you can do this:

var thisList = {
 "items":[
 {"name":"Item1", "image":"/img/item1", "chance":0.25},
 {"name":"Item2", "image":"/img/item2", "chance":0.25},
 {"name":"Item3", "image":"/img/item3", "chance":0.50}
 ] 
};
function getRandom(){
 var sum = 0;
 for(i=0;i<thisList.items.length;i++)
 {
 sum += thisList.items[i].chance;
 }
 var rnd = Math.floor(Math.random() * (sum * 100));
 console.log("The number is: " + rnd);
 var counter = 0;
 for(i=0;i<thisList.items.length;i++)
 {
 counter += thisList.items[i].chance * 100;
 if(counter > rnd){
 console.log(thisList.items[i]);
 break;
 }
 }
}
getRandom();

answered Mar 23, 2017 at 13:53
Sign up to request clarification or add additional context in comments.

4 Comments

This would work as long as it adds up to 1.00, am I correct?
@MartijnEbbens Yes it does. But i have updated my answer with another version, and now it works even when the chance sum > 1.00
I will always keep my chances rounding up to 1.00 or 100%, thanks for the handy dandy code tho! Seems to be working quite well!
The factors of 100 in this are completely unnecessary, but otherwise it's the algorithm I was describing
0

You need to look at the cumulative sum of all odds seen so far in the array. With the sample data you've given those values would be 0.25, 0.5, 1.0

Then given a random number in the range [0, 1), just pick the first entry where the cumulative value is less than that number.

Here's an example implementation:

const pickRandom = (() => {
 let target = Math.random(), total = 0.0;
 return (e, i, a) => {
 total += e.chance;
 return target < total;
 }
});
let picked = thisList.items.find(pickRandom());

The pickRandom function needs to be called exactly once per round, and returns a function that encapsulates the state necessary to accumulate the chances seen so far, and the random number that is to be used.

That function then becomes the predicate used by Array.prototype.find to extract the appropriate random item.

answered Mar 23, 2017 at 13:48

3 Comments

All chances should always add up to 1.0 | 100%, so you'd say if I'd where to take this list, var thisList = { "items":[ {"name":"Item1", "image":"/img/item1", "chance":0.25}, {"name":"Item2", "image":"/img/item2", "chance":0.25}, {"name":"Item3", "image":"/img/item3", "chance":0.50} ] } and then I'd get a random number using, var random = Math.random(); and then check if the number is less than it's chance for(x /*Loop*/){ if(thisList.items[x].chance <= random){ //var } } That would work?
No, not quite - the cumulative odds bit is what allows the random selection to pick the appropriate value in the range [0, 1) with the appropriate distribution. I've a meeting to go to so don't have time to flesh this out with code just now, but if you just start from 0 and add up the chances seen, you can just return as soon as the random number is lower than the cumulative chance.
If you still need code in another hour or so I'll have time to add some then

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.