为什么这个 Perl 洗牌函数不洗牌?
Why does this Perl shuffle function not shuffle?
#!/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;
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
my @arr = [qw(Foo Bar Baz Qux Quux Quuz)];
这是一个只有一个元素的数组,即元素 [qw(Foo Bar Baz Qux Quux Quuz)]
。因此这里没有什么可以洗牌的。您可能想要的是:
my @arr = qw(Foo Bar Baz Qux Quux Quuz);
这是您现有的代码:
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;
您的数组如下所示:
@arr = (
[qw(Foo Bar Baz Qux Quux Quuz)], # @arr element zero
# @arr element 1 doesn't exist
# @arr element 2 doesn't exist
# etc...
);
换句话说,您的数组包含单个元素。该元素是对包含 Foo, Bar, Baz, Qux, Quux, Quuz
的匿名数组的引用。您创建了一个多级数据结构。
你有两条前进的道路。如果你真的想要一个多级数据结构,那么对$arr[0]
引用的匿名数组中的元素进行排序可以这样洗牌:
@{$arr[0]} = shuffle(@{$arr[0]});
如果您不需要多级数据结构,您应该这样定义 @arr
:
@arr = qw(.........); # Notice the lack of [ and ]
然后洗牌变成:
@arr = shuffle(@arr);
[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 的一部分发行,这可以追溯到十多年前。它非常坚固,可以正常工作。
#!/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;
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
my @arr = [qw(Foo Bar Baz Qux Quux Quuz)];
这是一个只有一个元素的数组,即元素 [qw(Foo Bar Baz Qux Quux Quuz)]
。因此这里没有什么可以洗牌的。您可能想要的是:
my @arr = qw(Foo Bar Baz Qux Quux Quuz);
这是您现有的代码:
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;
您的数组如下所示:
@arr = (
[qw(Foo Bar Baz Qux Quux Quuz)], # @arr element zero
# @arr element 1 doesn't exist
# @arr element 2 doesn't exist
# etc...
);
换句话说,您的数组包含单个元素。该元素是对包含 Foo, Bar, Baz, Qux, Quux, Quuz
的匿名数组的引用。您创建了一个多级数据结构。
你有两条前进的道路。如果你真的想要一个多级数据结构,那么对$arr[0]
引用的匿名数组中的元素进行排序可以这样洗牌:
@{$arr[0]} = shuffle(@{$arr[0]});
如果您不需要多级数据结构,您应该这样定义 @arr
:
@arr = qw(.........); # Notice the lack of [ and ]
然后洗牌变成:
@arr = shuffle(@arr);
[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 的一部分发行,这可以追溯到十多年前。它非常坚固,可以正常工作。