in reply to Random Hash Key according to key frequency

my @thresh; my $total = 0; for ( keys %hash ) { $total += $hash{$_}; push @thresh, [ $total, $_ ]; } my $string; for ( 1 .. 30 ) { my $r = rand $total; my $i = 0; while ( $r > $thresh[$i][0] ) { $i++; } $string .= $thresh[$i][1]; }

jdporter
...porque es dificil estar guapo y blanco.

Replies are listed 'Best First'.
Re: Re: Random Hash Key according to key frequency
by iburrell (Chaplain) on Dec 04, 2002 at 18:38 UTC
    It is possible to do it without constructing the threshold array by stepping through the hash a second time.
    my $total = 0; foreach my $key (keys %hash) { $total += $hash->{$key}; } my $r = int(rand($total)); my $sum = 0; foreach my $key (keys %$hash) { $sum += $hash->{$key}; if ($r < $sum) return $key; }
    It might be possible to do only one pass through the hash using a technique like finding a random line from a file when the number of lines in the file isn't known.
      It might be possible to do only one pass through the hash using a technique like finding a random line from a file when the number of lines in the file isn't known.

      What... like this :-)

      sub random_key { my $hash = shift; my $line = 0; my $match = undef; while (my ($key, $value) = each %$hash) { $match = $key if rand($line += $value) < $value; }; return($match); };

      Update: removed unnecessary inner loop.