2009-08-19 20 views
5

Qualcuno sa come mescolare due array casualmente esattamente nello stesso modo in Perl? Ad esempio, dire ho questi due array:Come faccio a mescolare due array esattamente nello stesso modo in Perl?

prima di mischiare: matrice 1: 1, 2, 3, 4, 5 matrice 2: a, b, c, d, e

Dopo mescolamento : matrice 1: 2, 4, 5, 3, 1 matrice 2: b, d, e, c, un

Così ogni elemento in ogni matrice è legata al suo elemento equivalente.

risposta

22

Try (qualcosa di simile) questo:

use List::Util qw(shuffle); 
my @list1 = qw(a b c d e); 
my @list2 = qw(f g h i j); 
my @order = shuffle 0..$#list1; 
print @list1[@order]; 
print @list2[@order]; 
+1

++ per l'uso di sezioni di lista. Non mi ricordo di usarli tutte le volte che dovrei. – daotoad

+1

@daotoad: Io amo doppiamente le fette di hash: @foobar {qw (foo bar baz qux)} :-) –

+0

Grazie mille! – Abdel

6

Utilizzare List::Utilshuffle per shuffle un elenco di indici e mappare i risultati sugli array.

use strict; 
use warnings; 

use List::Util qw(shuffle); 

my @array1 = qw(a b c d e); 
my @array2 = 1..5; 

my @indexes = shuffle 0..$#array1; 
my @shuffle1 = map $array1[$_], @indexes; 
my @shuffle2 = map $array2[$_], @indexes; 

Aggiornamento Usa Chris soluzione Jester-Young. Array slices sono una scelta migliore che avrei dovuto pensare.

+1

Non è necessario utilizzare 'map'; gli array possono essere indicizzati da un'altra matrice, che contiene gli indici da ottenere. :-) –

9

Primo: gli array paralleli sono un potenziale segno di codice cattivo; dovresti vedere se puoi usare una serie di oggetti o di hash e salvarti da soli.

Tuttavia:

use List::Util qw(shuffle); 

sub shuffle_together { 
    my (@arrays) = @_; 

    my $length = @{ $arrays[0] }; 

    for my $array (@arrays) { 
    die "Arrays weren't all the same length" if @$array != $length; 
    } 

    my @shuffle_order = shuffle (0 .. $length - 1); 

    return map { 
    [ @{$_}[@shuffle_order] ] 
    } @arrays; 
} 

my ($numbers, $letters) = shuffle_together [1,2,3,4,5], ['a','b','c','d','e']; 

Fondamentalmente, utilizzare shuffle per produrre un elenco di indici in ordine casuale, e poi tagliare tutte le matrici con la stessa lista di indici.

+4

+1 per indicare che non dovresti avere array paralleli, ma array di qualcos'altro (matrici, hash, oggetti, qualunque cosa) che mantengono fisicamente i dati insieme. – Tanktalus

+1

+1 per verificare che la matrice abbia la stessa dimensione – lexu

+2

@Tanktalus: "should not" è eccessivamente forte. È odore di codice, ma a volte è proprio così. – ysth

6

Ecco un altro modo:

use strict; 
use warnings; 

use List::AllUtils qw(pairwise shuffle); 

my @list1 = qw(a b c d e); 
my @list2 = qw(f g h i j); 

my @shuffled_pairs = shuffle pairwise{[$a, $b]} @list1, @list2; 

for my $pair (@shuffled_pairs) { 
    print "$pair->[0]\t$pair->[1]\n"; 
} 

uscita:

 
C:\Temp> sfl 
e  j 
b  g 
d  i 
a  f 
c  h 

questo modo, è possibile scorrere direttamente sopra @shuffled_pairs senza bisogno di mantenere una matrice in più per gli indici ed evitare loop in stile C .

+0

+1 per usare il modo in cui stavo pensando. – Axeman

Problemi correlati