为什么这个 Perl shuffle 函数不shuffle?

gro*_*kus 2 perl

#!/usr/bin/perl

use Data::Dumper;
use strict;
use List::Util qw(shuffle);

my @arr = [qw(Foo Bar Baz Qux Quux Quuz)];
@arr = shuffle @arr;
print Dumper @arr;
Run Code Online (Sandbox Code Playgroud)

Perl 版本是 v5.32.0。我看到的结果总是Foo Bar Baz Qux Quux Quuz.

$ ~/tmp/shuffle.perl
$VAR1 = [
      'Foo',
      'Bar',
      'Baz',
      'Qux',
      'Quux',
      'Quuz'
    ];
$ /usr/bin/perl --version

This is perl 5, version 32, subversion 0 (v5.32.0) built for x86_64-linux-gnu-thread-multi
Run Code Online (Sandbox Code Playgroud)

Ste*_*ich 6

我的@arr = [qw(Foo Bar Baz Qux Quux Quuz)];

这是一个具有单个元素的数组,即 element [qw(Foo Bar Baz Qux Quux Quuz)]。因此这里没有什么可洗牌的。你可能想要的是:

 my @arr = qw(Foo Bar Baz Qux Quux Quuz);
Run Code Online (Sandbox Code Playgroud)


Dav*_*idO 5

这是您现有的代码:

use Data::Dumper;
use strict;
use List::Util qw(shuffle);

my @arr = [qw(Foo Bar Baz Qux Quux Quuz)];
@arr = shuffle @arr;
print Dumper @arr;
Run Code Online (Sandbox Code Playgroud)

您的数组如下所示:

@arr = (
    [qw(Foo Bar Baz Qux Quux Quuz)], # @arr element zero
                                     # @arr element 1 doesn't exist
                                     # @arr element 2 doesn't exist
                                     # etc...
);
Run Code Online (Sandbox Code Playgroud)

换句话说,您的数组包含一个元素。该元素是对包含 的匿名数组的引用Foo, Bar, Baz, Qux, Quux, Quuz。您创建了一个多级数据结构。

你有两条前进的道路。如果你真的想要一个多级数据结构,那么$arr[0]可以像这样对匿名数组中引用的元素进行排序:

@{$arr[0]} = shuffle(@{$arr[0]});
Run Code Online (Sandbox Code Playgroud)

如果您不需要多级数据结构,您应该这样定义@arr

@arr = qw(.........); # Notice the lack of [ and ]
Run Code Online (Sandbox Code Playgroud)

然后洗牌变成:

@arr = shuffle(@arr);
Run Code Online (Sandbox Code Playgroud)

[LIST]语法构成了一个匿名数组引用构造函数。您可能不需要匿名数组引用。

https://perldoc.perl.org/perlreftut是一个关于 Perl 参考的很好的教程。

https://perldoc.perl.org/perldsc是创建 Perl 数据结构的很好参考。

List::Util 的shuffle函数是Perl XS 中的Fisher Yates Shuffle实现(本质上是用 C 实现的)。它被大量使用并且是核心 Perl 发行版的一部分,并且自 Perl 5.8 以来一直作为 Perl 的一部分发行,这可以追溯到十多年前。它非常坚固,可以正常工作。