Hi,
If I have an array such as arr=[0.6,0.1,0.3]
How can I write pick and index randomly using these numbers in javaScript?
like pick 0, 60% of the times.
1, 10% of the times
2, 30% of the times
Thanks
Hi,
If I have an array such as arr=[0.6,0.1,0.3]
How can I write pick and index randomly using these numbers in javaScript?
like pick 0, 60% of the times.
1, 10% of the times
2, 30% of the times
Thanks
I assume that sum of elements = 1.
The idea is to make a new array called prArr
in which elements occurs as much times as their probability ratio.
let nums = [0.6, 0.1, 0.3]
let lc = 0.1
let randomPick = arr => {
let idx = 0, begin, count, prArr = []
arr.map(val => {
begin = idx
count = val / lc
for(; idx < count + begin; idx++)
prArr[idx] = val
})
let k = Math.floor(Math.random() * prArr.length)
return prArr[k]
}
for(let i = 0; i < 10; i++)
console.log(randomPick(nums))
Tip: You can adjust lc
to 0.01
or 0.001
based upon number of decimals
The idea is good. But you already have the probabilities so why not calculate with them?
You just do a Math.random(); and use this to get the index which correlates to this by using the cumulative probabilities, where every element has a certain area on the number scale from 0.0 up to 1.0 (e.g. element 0 is from 0.0 to 0.6, 1 is from 0.6 to 0.7 and 2 is 0.7 to 1.0):
const rnd = Math.random();
const arr = [0.6, 0.1, 0.3]
// The index and the cummulative probability
let index = -1;
let cum = 0;
// We add the cummulative probabilities and search till we get to where rnd is
arr.forEach((e, i) => {
if(rnd >= cum && rnd < cum + e) {
index = i;
}
cum += e;
});
Feel free to use also findIndex()
method with the same idea behind it:
let cum = 0;
const rnd = Math.random();
const arr = [0.6, 0.1, 0.3];
const index = arr.findIndex(e => { cum += e; return rnd < cum && rnd >= cum - e;})
(I am sorry for naming the one variable “cum”)
@JaielSoft, another one, based on subtracting elements from random value in each loop
let nums = [0.6, 0.1, 0.3]
let randomPick = arr => {
let k = Math.random()
// get the first value that makes "rnd int" negative on subtraction
let res = arr.find(val => (k -= val) < 0)
return res || arr.pop() // else pop the last one
}
for(let i = 0; i < 10; i++)
console.log(randomPick(nums))
For one-liners,
let randPick = (a, k=Math.random()) => a.find(v => (k -= v) < 0) || a.pop()
This one line works perfectly in the live example. But I am having trouble implementing it in my code.
what I did is create a function
randPick = (a, k=Math.random()) =>{ a.find(v => (k -= v) < 0) || a.pop()
}
Then in the main function that is running I used.
var randNum=this.randPick(percentVector[j]);
console.log(randNum);
For trying it I used
percentVector[j]=[0.5,0.5]
but the results is “undefined”
sorry if this is a trivial question but I am new at using JavaScript
you used {} in the lambda function so you need to add a return
statement. The original code didnt have them and a return
is implied.
edit: So if you dont get it the solution:
randPick = (a, k=Math.random()) =>{
return a.find(v => (k -= v) < 0) || a.pop();
}
(Although I dont like the (k -= v)
statement because it doesn’t adhere to general programming principals of making code that is easy to read and doesn’t hold any surprises. Also altering the state of a parameter, that should always be treated as constant, is not the best practice. But if it works out it’s fine. I like short code too after all)
Thank you!
you are right the longer code is actually more readable and easier to understand. I preferred the one line because my code already contains multiple nested loops. I am trying to do things with no more loops for things to be faster.