redo LABEL is the answer to your question, but here are a couple of "better" ways to select $maxclients unique elements from a bag (@weighteddiv).
This approach has the advantage of being simple, but it is relatively slow for large datasets and does not preserve the order in which the numbers were picked:
my @weighteddiv = (('1234') x 7, ('9876') x 42, ('1123') x 13); my %selected; my $maxclients = 2; until (keys %selected == $maxclients or @weighteddiv == 0) { my $i = rand(+@weighteddiv); # Not $# my $pluck = splice @weighteddiv, $i, 1; ++$selected{$pluck}; } my @selected = keys %selected; print "Selected: @selected\n";
You can preserve the order with a little more code in the loop to create @selected incrementally:
if (++$selected{$pluck} == 1) { push @selected, $pluck; }
Finally, a complicated but efficient solution involving probabilities:
my @weighteddiv = (('1234') x 7, ('9876') x 42, ('1123') x 13); my @selected; my $maxclients = 2; my %occurrence; foreach (@weighteddiv) { $occurrence{$_}++; } my $total = @weighteddiv; until (@selected == $maxclients or keys %occurrence == 0) { my $i = rand($total); keys %occurrence; # reset hash iterator while (my ($value, $count) = each %occurrence) { if ($i < $count) { push @selected, $value; delete $occurrence{$value}; $total -= $count; last; } $i -= $count; } } print "Selected: @selected\n";
Caveat: All solutions untested.
In reply to Re: removing the goto
by TilRMan
in thread removing the goto
by scoobyrico
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |