for( 0 .. $#$ref ) {
my $p = $_ + rand( $n-- );
@{$ref}[$p,$_] = @{$ref}[$_,$p];
}
You can even use List::Util 'shuffle':
sub my_shuffle2 {
my $ref = \@_;
use List::Util 'shuffle';
@{$ref}[0..$#$ref] = shuffle(@$ref);
return unless defined wantarray;
return wantarray ? @{ $ref } : $ref;
}
Caution: Contents may have been coded under pressure.
| [reply] [d/l] [select] |
| [reply] |
That will do it. Thanks for all the suggestions. This has helped a great deal.
I personally believe that now that you acknowledge BrowserUk for gaving you an actual solution to your problem, it is eventually clear what the problem really was, which has not been the case for most of us up to this point. Let me try a possibly better phrasing:
"Take N arrays and shuffle jointly all of their entries, redistribuiting them amongst the same N arrays while leaving their lenghts unchanged."
In which case, I admit I would have worked with references, and I would have never ever thought of BUk's cool and neat trick: I generally don't write subs that modify stuff that's passed to them in place, but just pass by value and take return values. This, in turn, is most often sensible. But then one shouldn't blindly generalize: occasionally I deviate from that rule adopting the backslashed prototypes. In fact I am not ashamed to confess that I had to stare at BUk's code for some time, to understand how it could achieve a similar semantics without them. Of course it's very trivial instead, but it can easily seem not to be after you've been "reasoning" along different lines for years.
Now, armed with:
- the precise definition of the problem,
- a convenient interface courtesy of @_'s aliasing properties,
let me tell you that you can adoopt just about any shuffling technique you like, including the much recommended "do not reinvent the wheel and use List::Util's shuffle()" one:
#!/usr/bin/perl
use strict;
use warnings;
use List::Util 'shuffle';
sub shuffit { @_[0..$#_] = shuffle @_; }
my @a = 'a' .. 'c';
my @b = 1 .. 4;
my @c = 'A' .. 'E';
shuffit @a, @b, @c;
print "A:= [ @a ]\nB:= [ @b ]\nC:= [ @c ]\n";
__END__
C:\temp>buk.pl
A:= [ 2 D C ]
B:= [ a 1 b 4 ]
C:= [ 3 B c E A ]
To complete the meditation above: while this remains a kind of interface that I'm not likely to resort to on a daily basis, I realize that it's both perfectly well suited for this particular case and for many other ones I may stumble upon. Which is the reason why I will always thank you for having brought up the question, even if the question itself is more of an aside in this respect.
| [reply] [d/l] [select] |