Random coefficients in arrays
Ok, so let's say I store some of my data, for example
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 would like to create a function that randomly selects an item from this list, the chances of which are 25% of getting [0], another 25% of getting [1] and 50% of getting [2]
Is it possible? If so, how would I do it?
Respectfully!
source to share
In fact, you can reproduce it like this: tou generates a number between 0 and 100, and then you loop through each element and add up the ability to check if it is in 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 the likelihood of a variant, 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();
source to share
You need to look at the cumulative sum of all the coefficients observed so far in the array. With the sample data you gave these values would be 0.25, 0.5, 1.0
Then, by specifying a random number in the range [0, 1), simply select the first record 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 function pickRandom
must be called exactly once per round and returns a function that encapsulates the state needed to accumulate the odds obtained so far and the random number to be used.
This function then becomes a predicate used Array.prototype.find
to retrieve the corresponding random element.
source to share
You can create a new array with the same element repeated for more time equal to 100. I am trying to explain with an example (and comments in the code):
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}
]
};
//Create an array balanced to 100
var balancedArray = new Array();
for(var i = 0; i < thisList.items.length; i++){
for(var j = 0; j < thisList.items[i].chance * 100; j++){
balancedArray.push(thisList.items[i].name);
}
}
console.log("New array should contains 100 elements: " + balancedArray.length);
//Get a random index from 1 to 100
var randomIndex = Math.floor(Math.random() * 100) + 1;
console.log("Random index: " + randomIndex);
//Finally get relative item (Arrays is zero-index, so decrement index)
console.log("Random item is: " + balancedArray[randomIndex-1]);
Hope this helps you. Bye.
source to share