我有一个字符串ID的散列。什么是洗牌ID的最佳方式?如何在一个散列值中进行混洗?
举个例子,我的哈希指定以下ID:
this => 0
is => 1
a => 2
test => 3
现在,我想随机混洗。一个例子的结果是:
this => 1
is => 0
a => 3
test => 2
我有一个字符串ID的散列。什么是洗牌ID的最佳方式?如何在一个散列值中进行混洗?
举个例子,我的哈希指定以下ID:
this => 0
is => 1
a => 2
test => 3
现在,我想随机混洗。一个例子的结果是:
this => 1
is => 0
a => 3
test => 2
你可以使用shuffle
方法List::Util
助阵:
use List::Util qw(shuffle);
...
my @values = shuffle(values %hash);
map { $hash{$_} = shift(@values) } (keys %hash);
'map'在无效的情况下是厌恶。 –
这只是一个风格问题,还是您有技术上的异议? (只是好奇) – Mat
当'map'返回列表时(即使在无效的情况下),这是一个真正的问题。现在这只是一个风格问题。有些人和我一样,认为依靠功能的副作用才能发挥作用是令人厌恶的。特别是当我们有一个简短的不使用副作用的构造时:'$ hash {$ _} =移动@values for keys%hash;'' –
哈希片将是我最清晰的方式:
#!/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;
你总是可以创建不同的哈希散列然后随机从其中的一个选择;) – hemlocker