如何在Perl中以完全相同的方式对两个数组进行洗牌?

Abd*_*del 5 arrays perl shuffle

有没有人知道如何在Perl中以完全相同的方式随机混乱两个数组?例如,假设我有这两个数组:

在改组之前:阵列1:1,2,3,4,5阵列2:a,b,c,d,e

改组后:阵列1:2,4,5,3,1阵列2:b,d,e,c,a

因此每个数组中的每个元素都绑定到它的等效元素.

Chr*_*ung 22

尝试(像这样):

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];
Run Code Online (Sandbox Code Playgroud)

  • @Brad Gilbert:我知道你认为把`qw(abcde)`变成`qw'a bcd e'可以改善突出显示,这一切都非常主观,但请记住```比``更难看(`大多数Perl代码使用`qw()`或`qw //'.我不确定可读性的损失值得改进颜色. (4认同)

hob*_*bbs 9

第一:并行数组坏代码的潜在迹象; 你应该看看你是否可以使用一组对象或哈希值,并为自己省去麻烦.

但是:

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'];
Run Code Online (Sandbox Code Playgroud)

基本上,用于shuffle以随机顺序生成索引列表,然后使用相同的索引列表对所有数组进行切片.

  • +1指出你不应该有并行数组,而是其他东西的数组(数组,散列,对象等等)将数据物理地保存在一起. (4认同)
  • @Tanktalus:"不应该"过于强大.这是代码味道,但有时候就是这样. (2认同)

dao*_*oad 6

使用List :: Util shuffle来混洗索引列表并将结果映射到数组.

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;
Run Code Online (Sandbox Code Playgroud)

更新 使用Chris Jester-Young的解决方案. 数组切片是我应该想到的更好的选择.


Sin*_*nür 6

这是另一种方式:

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";
}
Run Code Online (Sandbox Code Playgroud)

输出:

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

这样,您可以直接迭代而@shuffled_pairs无需为索引保留额外的数组并避免C风格的循环.