Martijn Ebbens
Martijn Ebbens

Reputation: 524

Random odds in arrays

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!

Upvotes: 4

Views: 841

Answers (2)

Alnitak
Alnitak

Reputation: 340045

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.

Upvotes: 0

Dr. Roggia
Dr. Roggia

Reputation: 1125

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();

Upvotes: 4

Related Questions