I'd not store the index, where the file begines, but the number of words in it.
Searching is then done by substracting the number of words from the random number.
As a final step, the file found is swapped with the last file and the number of words is substracted.
As you can see, your selected files are now in the last n positions of the array.#!/usr/bin/perl use strict; use warnings; my @number_of_words = ( { number => 10, name => 'file_a.txt' }, { number => 1, name => 'file_b.txt' }, { number => 3, name => 'file_c.txt' }, { number => 5, name => 'file_d.txt' }, { number => 10, name => 'file_e.txt' }, ); my $total_number_of_words = 29; my $select= 3; my $selected= 0; while ( $select-- ) { my $randomindex= rand $total_number_of_words; my $last_index= ( scalar @number_of_words ) - $selected - 1; my $i= $last_index+1; do { $randomindex-= $number_of_words[--$i]->{'number'}; } while ( $randomindex >= 0 ); $total_number_of_words-= $number_of_words[$i]->{'number'}; # print $number_of_words[$i]->{'name'},"\n"; @number_of_words[$i, $last_index]= @number_of_words[$last_index, $ +i]; ++$selected; } for (my $i= $#number_of_words - $selected; ++$i<=$#number_of_words;) { print $number_of_words[$i]->{'name'},"\n"; }
In reply to Re: Efficiently selecting a random, weighted element
by Skeeve
in thread Efficiently selecting a random, weighted element
by jimt
For: | Use: | ||
& | & | ||
< | < | ||
> | > | ||
[ | [ | ||
] | ] |