2009-08-19 7 views
5

¿Alguien sabe cómo mezclar aleatoriamente dos matrices exactamente de la misma manera en Perl? Por ejemplo, decir que tengo estas dos matrices:¿Cómo mezclo dos arreglos exactamente de la misma manera en Perl?

antes de barajar: array 1: 1, 2, 3, 4, 5 matriz 2: a, b, c, d, e

Después de barajado : matriz 1: 2, 4, 5, 3, 1 matriz 2: b, d, e, c, a

De modo que cada elemento de cada matriz está vinculado a su elemento equivalente.

Respuesta

22

Try (algo así como) esto:

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

++ para el uso de secciones de lista. No recuerdo usarlos tan a menudo como debería. – daotoad

+1

@daotoad: me encantan las rebanadas de hash: @foobar {qw (foo bar baz qux)} :-) –

+0

¡Muchas gracias! – Abdel

6

Use List::Utilshuffle para mezclar una lista de índices y asignar los resultados a los arreglos.

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; 

actualización Uso Chris solución de Jester-Young. Array slices son una mejor opción que debería haber pensado.

+1

No es necesario que use 'map'; las matrices pueden ser indexadas por otra matriz, que contiene los índices para obtener. :-) –

9

Primero: formaciones paralelas son un signo potencial de mal código; Debería ver si puede usar una matriz de objetos o hashes y ahorrarse ese problema.

No obstante:

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']; 

Básicamente, utilice shuffle para producir una lista de índices en orden aleatorio y, a continuación, cortar todas las matrices con la misma lista de índices.

+4

+1 para señalar que no deberías tener matrices paralelas, sino matrices de otra cosa (matrices, hashes, objetos, lo que sea)) que mantienen los datos juntos físicamente. – Tanktalus

+1

+1 para asegurarse de que la matriz ES del mismo tamaño – lexu

+2

@Tanktalus: "no debería" es demasiado fuerte. Es código malicioso, pero a veces es así. – ysth

6

Aquí es otra manera:

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"; 
} 

Salida:

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

De esta manera, se puede iterar directamente sobre @shuffled_pairs sin necesidad de mantener una serie extra para los índices y evitar bucles de tipo C .

+0

+1 por usar la forma en que estaba pensando. – Axeman

Cuestiones relacionadas