How to retrieve a row, biased by populatity?

Chris Devers cdevers at pobox.com
Tue Aug 21 21:38:06 BST 2012


On Tue, Aug 21, 2012 at 4:22 PM, Dave Hodgkinson <davehodg at gmail.com> wrote:

>
> Possibly a perl question. SQL would do...
>
> Given a set of data, say bands, with each having a ranking, either a
> review metric or a sales ranking, how would you retrieve a random
> row, but biased towards the higher ranking?
>

If you have access to a copy of _Mastering Algorithms with Perl_, it had
some examples like this in chapter 14.

The sample code can be downloaded from O’Reilly:

http://examples.oreilly.com/9781565923980/

The one you’re interested seems to be the rand-dist-weighted example,
pasted below:

$ cat rand-dist-weighted
#!/usr/bin/perl

# $selection = rand_dist_weighted( \%dist, \@key_order, $total_weight )
#   Select an element from %dist.  The total of the weights, and the
#   keys sorted by their weights can be provided, or else they are
#   computed.
sub rand_dist_weighted {
    my( $dist, $key_order, $total_weight ) = @_;
    my $running_weight;

    $key_order = [ sort { $dist->{$a} <=> $dist->{$b} } keys %$dist ]
        unless $key_order;
    unless ( $total_weight ) {
        foreach (@$key_order) { $total_weight += $dist->{$_} }
    }

    # Get a random value.
    my $rand = rand( $total_weight );

    # Use it to determine a key.
    foreach my $key (@$key_order) {
        return $key if ($running_weight += $dist->{$key}) >= $rand;
    }
}

%smartie_weights = ( orange => 3, green => 10, pink => 8, brown => 10,
    tan => 0, red => 6, blue => 11, yellow => 7,
    purple => 5);

print rand_dist_weighted( \%smartie_weights ), "\n";

$smartie_weight = 0;
@smartie_order = sort { $smartie_weights{$a} <=> $smartie_weights{$b} }
    keys %smartie_weights;
for (@smartie_order) { $smartie_weight += $smartie_weights{$_} }

for ( 0..50 ) {
    print rand_dist_weighted( \%smartie_weights, \@smartie_order,
        $smartie_weight ), "\n";
}


-- 
Chris Devers


More information about the london.pm mailing list