【问题标题】:How do I shuffle two arrays in exactly the same way in Perl?如何在 Perl 中以完全相同的方式洗牌两个数组?
【发布时间】:2009-08-19 00:06:41
【问题描述】:

有谁知道如何在 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

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

【问题讨论】:

    标签: perl arrays shuffle


    【解决方案1】:

    试试(类似的)这个:

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

    【讨论】:

    • ++ 用于列表切片。我不记得经常使用它们。
    • @daotoad:我非常喜欢哈希切片:@foobar{qw(foo bar baz qux)} :-)
    • @Brad Gilbert:我知道您认为将qw(a b c d e) 转换为qw'a b c d e' 可以提高突出显示效果,这都是非常主观的,但请记住'( 更难看到大多数 Perl 代码使用qw()qw//。我不确定在易读性上的损失是否值得颜色的改进。
    • 我会添加一个:# optional... @list1 = @list1[@order]; @list2= @list2[@order];
    • @Sinan:同意,“回滚”链接正盯着我看,很诱人。 :-)(顺便说一句,我也喜欢你的方法,我 +1 了;但我太喜欢列表/散列切片而不使用这种方法。:-P)
    【解决方案2】:

    首先:并行数组错误代码的潜在标志;你应该看看你是否可以使用一个对象或哈希数组来省去这个麻烦。

    尽管如此:

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

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

    【讨论】:

    • +1 指出您不应该有并行数组,而是其他东西(数组、散列、对象等)的数组,它们可以将数据物理地保持在一起。
    • @Tanktalus:“不应该”过于强烈。这是代码异味,但有时就是这样。
    【解决方案3】:

    使用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;
    

    更新 使用 Chris Jester-Young 的解决方案。 Array slices 是我应该想到的更好的选择。

    【讨论】:

    • 你不需要使用map;数组可以由另一个数组索引,该数组包含要获取的索引。 :-)
    【解决方案4】:

    这是另一种方式:

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

    输出:

    C:\Temp> sfl Ĵ 乙克 我 一个 ch

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

    【讨论】:

      猜你喜欢
      • 2022-01-04
      • 1970-01-01
      • 2012-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-22
      相关资源
      最近更新 更多