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

I am using the well known method of randomizing an array and I can't get the dang thing to work.
my $username = shuffle(\@usernames); print $username; # prints 0!! sub shuffle { my $array = shift; my $i; for ($i = @$array; --$i; ) { my $j = int rand ($i+1); next if $i == $j; @$array[$i,$j] = @$array[$j,$i]; } }
What is wrong with this?

Replies are listed 'Best First'.
Re: randomize array
by runrig (Abbot) on Mar 29, 2006 at 01:17 UTC
    Zero is what your function (by way of the for loop) is (implicitly) returning. If you intended to return something else, you should explicitly return something. Note that you are shuffling the @usernames array in place...you can see that with print "@usernames\n";
Re: randomize array
by rafl (Friar) on Mar 29, 2006 at 01:05 UTC

    How about

    use List::Util qw(shuffle); my @shuffled_usernames = shuffle(@usernames);

    Cheers, Flo

Re: randomize array
by bart (Canon) on Mar 29, 2006 at 06:54 UTC
    runrig is exactly on the spot...

    But, are you aware that you're changing your original array, in place? Thus, your function doesn't have to return anything, you can just print out the original array. An usually, that's an undesired side effect.

Re: randomize array
by Cody Pendant (Prior) on Mar 29, 2006 at 08:16 UTC
    It seems like you just want "a random item from the array" in which case you don't need to sort the array, you just need $username = $usernames[rand(@usernames)], surely?


    ($_='kkvvttuu bbooppuuiiffss qqffssmm iibbddllffss')
    =~y~b-v~a-z~s; print
Re: randomize array
by NetWallah (Canon) on Mar 29, 2006 at 05:09 UTC
    If you are expecting the statement
    @$array[$i,$j] = @$array[$j,$i];
    to interchange the elements, you are missing a step or two. You need to do something like:
    my $temp = $array->[$i,$j]; $array->[$i,$j] = $array->[$j,$i]; $array->[$j,$i] = $temp;
    Update:I stand corrected - Thanks, Thelonius. Please Ignore this node. <Feeble_excuse>Late night brain block did not process the array-ref-slice syntax correctly</Feeble_excuse>.

         "For every complex problem, there is a simple answer ... and it is wrong." --H.L. Mencken

      If you are expecting the statement ... to interchange the elements, you are missing a step or two.
      No, that part works fine:
      my @usernames = qw(zero one two three four five six); testswap(\@usernames); print join(" ", @usernames), "\n"; sub testswap { my $array = shift; my $i = 2; my $j = 5; @$array[$i, $j] = @$array[$j, $i]; }
      Prints: zero one five three four two six

      As runrig pointed out, you're not returing a value, you could put return $array->[0] at the end of the subroutine.

      If you just want to pick one element out of the list, you're going to too much trouble. You can just say:

      my $username = $usernames[rand(@usernames)];