Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

rand + shift || pop

by magnus (Pilgrim)
on Dec 21, 2010 at 15:18 UTC ( #878281=perlquestion: print w/replies, xml ) Need Help??

magnus has asked for the wisdom of the Perl Monks concerning the following question:

i'm not able to find this in my senility and i'm hoping it can be done:

I have a simple array of elements and i want to randomly chose an element out of that array, but when i do, i want it removed from the array. similar to pop or shift, but it doesn't necessarily take it from the ends...

thanks in advance for any help.

Replies are listed 'Best First'.
Re: rand + shift || pop
by toolic (Bishop) on Dec 21, 2010 at 15:26 UTC
    Another way: shuffle
    use warnings; use strict; use List::Util qw(shuffle); my @nums = shuffle(1 .. 10); my $sample = pop @nums; print "sample = $sample\n";
Re: rand + shift || pop
by Your Mother (Archbishop) on Dec 21, 2010 at 15:24 UTC

    A way-

    my @list = ( "a" .. "z" ); while ( @list ) { print splice(@list,rand(@list),1), $/; }
Re: rand + shift || pop
by kennethk (Abbot) on Dec 21, 2010 at 15:28 UTC
    In addition to the lovely splice-based approaches listed above, if you are simply using your array as a grab-bag and have no need to maintain order, combining shuffle from List::Util (core) with pop or shift should yield a cleaner solution:

    #!/usr/bin/perl use strict; use warnings; use List::Util qw (shuffle); my @array = (0 .. 9); @array = shuffle @array; print pop(@array), "\n", @array;

    Note this is discussed in perlfaq4's How do I shuffle an array randomly?.

      While splice is helpful, shuffle + shift || pop is a very simple and elegant solution. Didn't even twig on that one. Thanks very much.
        Shuffleing is O(n) and spliceing is O(1), this may matter if your array is large.

        Update: Oops, my understanding of splice was wrong. See JavaFan and ikegami below.

Re: rand + shift || pop
by Anonymous Monk on Dec 21, 2010 at 15:22 UTC
Re: rand + shift || pop
by Anonymous Monk on Dec 21, 2010 at 15:24 UTC
    perldoc -f splice
    $ perl -MDDS -e " @f = 1..3; Dump(\@f); warn splice @f, rand(@f),1; Du +mp( \@f )" $ARRAY1 = [ 1, 2, 3 ]; 1 at -e line 1. $ARRAY1 = [ 2, 3 ];
Re: YAW: rand + shift || pop
by ww (Archbishop) on Dec 21, 2010 at 21:27 UTC

    Yet Another Way (for the senile who don't remember shift):

    #!/usr/bin/perl use strict; use warnings; # 878281 my @array = ("a", "b", "c", "d", "e", "f",); my $i = int(rand(6)); my $array = $array[$i]; undef $array[$i]; print "\t\$i: $i and \$array: $array \n"; print "\tRemaining \@array: \t"; no warnings qq(uninitialized); for $array(@array) { if (defined($array)) { print $array . "\t"; } else { next; } } print "\n done!\n";

    Looping around this, if one wishes to exhaust the array, is left as an exercise for the interested.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://878281]
Approved by kennethk
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2023-12-02 18:56 GMT
Find Nodes?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?

    Results (18 votes). Check out past polls.