Digger3000

07-04-2007, 02:02 PM

Let's say I have something like this: $colors=array("red", "blue"); And I want to randomly echo one of the things in the array. But let's say I want it to be more likely for it to be red than blue. I guess I could put red into the array twice, but is there a quicker way? I'm very, very lazy.

CFMaBiSmAd

07-04-2007, 02:20 PM

The only easy way, without actually writing out the probability equations using PHP code, is to create an array with the correct number of entries with the "weight" you want -

$colors=array("red", "blue"); // gives one out of two chance for red

$colors=array("red", "red", "blue"); // gives two out of three chance for red

$colors=array("red", "red", "red", "blue"); // gives three out of four chance for redYou could shorten the data structure to a color/weight pair, but you would need to add code to produce the expanded array with all the entries. To get a computer to randomly pick from the weighted possibilities, you need a "pool" of the available choices to pick from.

You can use the shuffle(...) or array_rand(...) function instead of a random number to actually generate a random entry.

Digger3000

07-04-2007, 02:44 PM

I made up a solution that seems like it could work. What do you think?

$colors=array("2|red", "1|blue");

$newcolors=array();

foreach($colors as $key => $value) {

$split=explode("|", $value);

$probability=$split[0];

$thecolor=$split[1];

$i=1;

while($i <= $probability) {

$newcolors[]=$thecolor;

$i++;

}

}

CFMaBiSmAd

07-04-2007, 02:57 PM

Try it and see if it produces the array you expect. That's where writting, testing, and debugging code gets fun, getting code to do what you want.

Digger3000

07-04-2007, 03:15 PM

I did print_r($newcolors); and got this: "Array ( [0] => Red [1] => Red [2] => Blue )" So it seems to work.

ralph l mayo

07-04-2007, 11:42 PM

Just another method you can use if it suits you... it simulates an array with duplicates determining priority instead of actually making one, but I don't know whether it's faster or not.

function array_weighted_rand($ary)

{

# Pick a random index as if the array was arranged so that it actually

# had more entries of the values with higher probabilities

# eg. for values = [ red, blue, green]

# and probabilities = [ 2, 1, 3]

# assume something like:

# 0 => red

# 1 => red

# 2 => blue

# 3 => green

# 4 => green

# 5 => green

$prob_idx = mt_rand(0, array_sum(array_values($ary)) - 1);

# Find where the selected index maps to the real indices by calculating

# a running sum on the probabilities and returning whenever the index

# is exceeded.

$running_sum = 0;

foreach ($ary as $value=>$prob)

{

$running_sum += $prob;

if ($running_sum > $prob_idx)

return $value;

}

}

$colors = array(

'red' => 2,

'blue' => 1,

'green' => 3

);

$picks = array(

'red' => 0,

'blue' => 0,

'green' => 0

);

for ($idx = 0; $idx < 100000; ++$idx)

{

++$picks[array_weighted_rand($colors)];

}

print_r($picks);