Actually, even this is problematic. Because you need to go through the list in a defined order to ensure that each item has its respective probabilities. So you really do need the array refs ... but you need them in a list, not a hash.
Then, when you generate a number, you first loop through summing $_->[1]:my @items = ( ["foo", 1], ["bar", 3], ["baz", 4], ["quux", 9] );
and then you generate a number from that, and then find the item in the total:use List::Util; my $total_weight = List::Util::sum(map { $_->[1] } @items);
Ok, that's a bit convoluted, but I don't quite want to do someone's homework ;-) Anyway, the point is that if, when iterating over the hash, you end up with the hash being reordered from lookup to lookup, I don't think you'll get precisely the correct distribution. (Of course, I'm assuming a perfectly random rand function, but that is a separate problem.)my $pick = int(rand($total_weight)); my $picked_item = (List::Util::first { $pick -= $_->[1]; $pick < 0 } + @items)->[0];
Update: fix some minor formatting, and off-by-one error (was $pick <= 0)
In reply to Re^3: Picking a random item through probability
by Tanktalus
in thread Picking a random item through probability
by muba
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |