That has the advantage of just one rand().

Things you have to look out for, though:

BTW, I think the comparison should be $r < 0.

One could stick the weight at the end of the list:

use strict ; use warnings ; my $RUNS = 100_000 ; my $data = [[a => 0.1], [b => 0.5], [c => 0.4], [c => 0]] ; my %count; foreach (1 .. $RUNS) { my $total_weight = $data->[-1]->[1] ; if (!$total_weight) { $total_weight += $_->[1] for @$data ; $data->[-1]->[1] = $total_weight ; } ; my $pick; my $r = rand($total_weight) ; foreach (@$data) { if (($r -= $_->[1]) < 0) { $pick = $_->[0] ; la +st ; } ; } ; $count{$pick}++ ; } ; while (my ($k, $v) = each %count) { printf "%s: %5.2f%%\n", $k, 100 * $v / $RUNS ; } ; __END__ c: 39.89% a: 9.92% b: 50.19%

Noting that we can duplicate the last value in the total weight entry, so in the (unlikely) event of not stopping on the last real entry, the last value will come from the weight entry.

This is, like the other solutions, a linear search along your list of possible values. You can speed this up by putting the popular stuff earlier in the list. If that is still too slow -- you have lots of possible values and you're doing this a lot, you can sub divide the list into groups, and prefix each group with its total weight -- then step along the groups reducing $r as above, and then within the selected group increasing $r.... but only if you really have to !


In reply to Re^2: How do I get a random index with weighting? by gone2015
in thread How do I get a random index with weighting? by m_al

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.