Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: Select value from array w/o replacement (or destroying the array)

by fenLisesi (Priest)
on Dec 03, 2007 at 09:33 UTC ( #654527=note: print w/ replies, xml ) Need Help??


in reply to Select value from array w/o replacement (or destroying the array)

I think tye's solution is the best. If for some reason you would prefer one of the others, the answer would depend on how big n is compared to the size of the array. If it is small, say, smaller than 10%, then just pick a random number in the range 0..$#a and pick another one if that had been picked before. Such collisions should be rare for small n / @a; If it is larger, then shuffle first, but do not shuffle the array itself, especially if the array elements themselves tend to be big (which doesn't seem to be the case here). Instead, create a separate index array and shuffle that -- something like @indices = shuffle 0..$#a. Below, I tried to add comments to tye's code. I may have messed up, so wait until wiser monks have had a chance to peruse it.

use strict; use warnings; ## How many elements to pick use constant N => 10; ## The original array that must not be altered my @letters = ('a'..'z'); ##-----------------------------------------------------+ ## Generate code that will pick an element from ## @letters at each iteration without repeating ##-----------------------------------------------------+ my $picker_of_next_rand = gen_picker( \@letters ); ## Now execute (iterate) that code N times for (1..N) { print $picker_of_next_rand->(); } print "\n"; ## look nice print @letters, "\n"; ## original untouched exit( 0 ); ##-----------------------------------------------------+ ## This sub generates and returns code that will pick ## a random element from @$aref at each iteration ## without repeating ##-----------------------------------------------------+ sub gen_picker { my ($aref) = @_; my @indices = 0 .. $#$aref; ## closes on @indices return sub { if (! @indices) { die "No more items left to pick from"; } ##---------------------------------------------+ ## pick an int in the range (0 .. $#$aref), ## the range of the array's indices ##---------------------------------------------+ my $random_index = int rand @indices; ## $pick is the element at the random_index my $pick = $aref->[ $indices[ $random_index ] ]; ##---------------------------------------------+ ## We are about to pop the index array. Save ## the element at the pop-end of the index array ## by copying it into the position of the $pick ## (clobber index of $pick, won't be used again) ##---------------------------------------------+ $indices[ $random_index ] = $indices[ -1 ]; ## Now it is safe to pop the index array pop @indices; return $pick; }; }

which prints something like the following:

vkdbfymxie abcdefghijklmnopqrstuvwxyz


Comment on Re: Select value from array w/o replacement (or destroying the array)
Select or Download Code
Replies are listed 'Best First'.
Re^2: Select value from array w/o replacement (or destroying the array)
by BioNrd (Monk) on Dec 04, 2007 at 16:30 UTC
    I agree that this solution is going to suit my needs. The code works really well, but I don't understand a part of it.
    my $picker_of_next_rand = gen_picker( \@letters ); print $picker_of_next_rand->();
    I under stand that is is a reference/dereference type thing.

    What I don't understand is how to use the variable $pick in a meaningful (non-global) way. i.e. $var_to_use_later = $list[$pick]; I have had trouble with reference/dereference structure before, and I have tried to use the camal book. It is not sinking in, and combined with a bit of code I am not familar with...it is a headache for me.

    I appreciate all that has been done to this point for me, it is just that last little push in the right direction I need.

    Thanks...Bio.

    Even a blind squirrel finds a nut sometimes.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://654527]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (12)
As of 2015-07-31 18:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (280 votes), past polls