我有一个字符串ID的哈希值。什么是洗牌的最佳方法?
例如,我的哈希值分配了以下ID:
this => 0
is => 1
a => 2
test => 3
现在我想随机改变它。一个示例结果将是:
this => 1
is => 0
a => 3
test => 2
答案 0 :(得分:7)
您可以使用List::Util
中的shuffle
方法提供帮助:
use List::Util qw(shuffle);
...
my @values = shuffle(values %hash);
map { $hash{$_} = shift(@values) } (keys %hash);
答案 1 :(得分:4)
哈希切片对我来说是最清晰的方式:
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw/shuffle/;
use Data::Dumper;
my %h = (
this => 0,
is => 1,
a => 2,
test => 3,
);
@h{keys %h} = shuffle values %h;
print Dumper \%h;
这有一个缺点,即当你拉出所有键和值时,巨大的哈希会占用大量内存。更有效(从内存的角度来看)解决方案是:
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw/shuffle/;
use Data::Dumper;
my %h = (
this => 0,
is => 1,
a => 2,
test => 3,
);
{ #bareblock to cause @keys to be garbage collected
my @keys = shuffle keys %h;
while (my $k1 = each %h) {
my $k2 = shift @keys;
@h{$k1, $k2} = @h{$k2, $k1};
}
}
print Dumper \%h;
此代码的好处是只需复制键(而不是键和值)。
以下代码不会随机化值(Perl 5.8.1除外,其中键的顺序保证是随机的),但它会混淆顺序。它确实具有在没有太多额外内存使用的情况下正常工作的好处:
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw/shuffle/;
use Data::Dumper;
my %h = (
this => 0,
is => 1,
a => 2,
test => 3,
);
my $k1 = each %h;
while (defined(my $k2 = each %h)) {
@h{$k1, $k2} = @h{$k2, $k1};
last unless defined($k1 = each %h);
}
print Dumper \%h;