On Tue, Aug 21, 2012 at 4:22 PM, Dave Hodgkinson <daveh...@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