3

I'm using Javascript and I would like to pick a random value out of an array. The problem is that actually I want to do the selection with specific proportions.

What does it mean?

I have the following values - 'INFO', 'CRITICAL', 'DEBUG', 'ERROR'

And I want to pick the values with the following ratio:

1. INFO - 30% 2. CRITICAL - 5% 3. DEBUG - 55% 4. ERROR - 10%

This is how I currently randomally pick a value -

var diffSev = ['INFO', 'CRITICAL', 'DEBUG', 'ERROR']
output['testSev'] = diffSev[Math.floor(Math.random() * diffSev.length)];

I would like to add a logic that will pick the values with the ratio that I need. Thanks!!

Dorian Mazur
  • 514
  • 2
  • 12
  • 1
    Maybe this post can help you : https://stackoverflow.com/questions/11552158/percentage-chance-of-saying-something – Bambou Apr 24 '19 at 15:02
  • 3
    Possible duplicate of [Percentage chance of saying something?](https://stackoverflow.com/questions/11552158/percentage-chance-of-saying-something) – malifa Apr 24 '19 at 15:03
  • @Bambou - while it is a duplicate, the answers there aren't as good as the accepted answer on the question lexith flagged (after I'd already started to write the same algorithm below) – symcbean Apr 24 '19 at 15:19

3 Answers3

2

You can have an array of size 20 that contains the relative portion of your labels, and represent the exact percentage of each label.
Then, all you need to do is random of 1-20, the result will use as index to choose from the array.

 var diffSev = [
 'CRITICAL', 
 'ERROR', 'ERROR',
 'INFO', 'INFO', 'INFO', 'INFO', 'INFO', 'INFO',
 'DEBUG', 'DEBUG', 'DEBUG', 'DEBUG', 'DEBUG', 'DEBUG', 'DEBUG', 'DEBUG', 'DEBUG', 'DEBUG', 'DEBUG'
 ]

 return diffSev[Math.floor(Math.random() * 20)];
dorony
  • 1,008
  • 1
  • 14
  • 31
0

Look at the integral of the probability, not the probability itself.

Since you are using nominal values, the order does not impact the functionality but by sorting them by most likely first, you would have (an undetectable) performance improvement.

function getWeightedSeverity()
{
  var cummprob =[0.55,    0.85,   0.95  , 1.0];  
  var labels   =['DEBUG','INFO','ERROR','CRITICAL'];
  var x=math.random();
  var y=0;
  for (y=0; y<cummprob.length, y++) {
    if (cummprob[y]>=x) break;
  }
  return labels[y];
}
symcbean
  • 47,736
  • 6
  • 59
  • 94
-2

try something similar to this

 var diffSev = ['INFO', 'CRITICAL', 'DEBUG', 'ERROR']
 var rand = diffSev[Math.floor(Math.random() * 100)];

switch (rand) {
    case rand < 30 :
        output['testSev'] = diffSev[0]
        break;
    case rand > 30 && rand < 36:
        output['testSev'] = diffSev[1]
        break;
    case rand > 35 && rand < 91:
        output['testSev'] = diffSev[2]
        break;
    case rand > 90:
        output['testSev'] = diffSev[3]
        break;
}
zach
  • 72
  • 4