2009-08-19 7 views
5

Kann jemand zwei Arrays in Perl auf genau dieselbe Weise mischen? Zum Beispiel sagen, ich habe diese beiden Arrays:Wie mische ich zwei Arrays auf genau dieselbe Weise in Perl?

Vor Shuffling: Array 1: 1, 2, 3, 4, 5 Feld 2: a, b, c, d, e

Nach shuffling : Array 1: 2, 4, 5, 3, 1 Array 2: b, d, e, c, a

So ist jedes Element in jedem Array an sein äquivalentes Element gebunden.

Antwort

22

Versuchen (so etwas wie) diese:

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

++ für die Verwendung von Listenscheiben. Ich kann mich nicht daran erinnern, sie so oft zu benutzen wie ich sollte. – daotoad

+1

@daotoad: Ich liebe Hash-Slots doppelt: @foobar {qw (foo bar baz qux)} :-) –

+0

Vielen Dank! – Abdel

6

Verwenden Sie List::Utilshuffle, um eine Liste von Indizes zu mischen und die Ergebnisse den Arrays zuzuordnen.

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; 

aktualisieren Verwenden Chris Jester-Young-Lösung. Array slices sind eine bessere Wahl, an die ich hätte denken sollen.

+1

Sie müssen 'map' nicht verwenden; Arrays können von einem anderen Array indiziert werden, das die zu erhaltenden Indizes enthält. :-) –

9

Erstens: parallele Anordnungen sind ein mögliches Zeichen des schlechten Code; Sie sollten sehen, ob Sie ein Array von Objekten oder Hashes verwenden können und sich diese Mühe ersparen können.

Dennoch:

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

Grundsätzlich shuffle verwenden, um eine Liste von Indizes in zufälliger Reihenfolge, zu erzeugen, und dann alle der Arrays mit der gleichen Liste von Indizes zu schneiden.

+4

+1 für Hinweis darauf, dass Sie keine parallelen Arrays haben sollten, sondern Arrays von etwas anderem (Arrays, Hashes, Objekte, was auch immer), die die Daten physisch zusammenhalten. – Tanktalus

+1

+1 um sicherzustellen, dass das Array die gleiche Größe haben – lexu

+2

@Tanktalus: "sollte nicht" ist übermäßig stark. Es ist Code-Geruch, aber manchmal ist es genau so wie es ist. – ysth

6

ist hier eine andere Art und Weise:

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

Ausgang:

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

Auf diese Weise können Sie direkt über @shuffled_pairs laufen, ohne dass eine zusätzliche Array für die Indizes zu halten und C-Stil Schleifen vermeiden .

+0

+1 für die Verwendung der Art, wie ich dachte. – Axeman

Verwandte Themen