perl:洗牌值排序哈希?
首先为我的英语感到抱歉-我希望你能理解我 有一个散列:perl:洗牌值排序哈希?,perl,sorting,hash,Perl,Sorting,Hash,首先为我的英语感到抱歉-我希望你能理解我 有一个散列: $hash{a} = 1; $hash{b} = 3; $hash{c} = 3; $hash{d} = 2; $hash{e} = 1; $hash{f} = 1; 我想按值(而不是键)对其进行排序,因此我有: for my $key ( sort { $hash{ $a } <=> $hash{ $b } } keys %hash ) { ... } 对于我的$key(排序{$hash{$a}$hash{$b}}key
$hash{a} = 1;
$hash{b} = 3;
$hash{c} = 3;
$hash{d} = 2;
$hash{e} = 1;
$hash{f} = 1;
我想按值(而不是键)对其进行排序,因此我有:
for my $key ( sort { $hash{ $a } <=> $hash{ $b } } keys %hash ) { ... }
对于我的$key(排序{$hash{$a}$hash{$b}}keys%hash){…}
首先我得到所有值为1的键,然后是值为2的键,等等。。。太好了
但是,如果哈希值不变,则键的顺序(按值排序)总是相同的
问题:我如何洗牌排序结果,所以每次运行“for”循环时,我都会得到不同的键顺序(值为1、值为2等)?您可以有两个升序和降序函数,并相应地使用它们,如
sub hasAscending {
$hash{$a} <=> $hash{$b};
}
sub hashDescending {
$hash{$b} <=> $hash{$a};
}
foreach $key (sort hashAscending (keys(%hash))) {
print "\t$hash{$key} \t\t $key\n";
}
foreach $key (sort hashDescending (keys(%hash))) {
print "\t$hash{$key} \t\t $key\n";
}
sub-hass{
$hash{$a}$hash{$b};
}
子散列{
$hash{$b}$hash{$a};
}
foreach$key(排序哈希升序(key(%hash))){
打印“\t$hash{$key}\t\t$key\n”;
}
foreach$键(排序哈希降序(键(%哈希))){
打印“\t$hash{$key}\t\t$key\n”;
}
您似乎希望随机循环键
Perl不按顺序或排序顺序存储,但这对您来说似乎不够随机,因此您可能需要创建一个键数组并循环使用它
首先,用键填充数组,然后使用随机数算法(1..$#length_of_array)将数组中该位置的键推送到数组中的_键
如果您试图随机化按值排序散列的键,则会有一点不同
my%hash=(a=>1,b=>3,c=>3,d=>2,e=>1,f=>1);
我的%hash\u by\u val;
对于我的$key(排序{$hash{$a}$hash{$b}}键%hash){
通过{$hash{$key}},$key推送{$hash};
}
对于我的$key(按值对键%hash\u进行排序){
my@arr=@{$hash\u by_val{$key};
我的$arr_ubound=$#arr;
对于(0..$arr_ubound){
我的$randnum=int(兰特($arr_ubound));
my$val=拼接(@arr$randnum,1);
$arr_ubound--;
打印“$key:$val\n”#注意:输出因b/t运行而异
}
}
我不太清楚您的需求,但这样可以吗:
use List::Util qw(shuffle);
my %hash;
$hash{a} = 1;
$hash{b} = 3;
$hash{c} = 3;
$hash{d} = 2;
$hash{e} = 1;
$hash{f} = 1;
for my $key (sort { $hash{ $a } <=> $hash{ $b } } shuffle( keys %hash )) {
say "hash{$key} = $hash{$key}"
}
use List::Util qw(shuffle);
我的%hash;
$hash{a}=1;
$hash{b}=3;
$hash{c}=3;
$hash{d}=2;
$hash{e}=1;
$hash{f}=1;
对于我的$key(排序{$hash{$a}$hash{$b}}shuffle(key%hash)){
说“hash{$key}=$hash{$key}”
}
您只需添加另一个排序级别,当常规排序方法无法区分两个值时,将使用该级别。例如:
sort { METHOD_1 || METHOD_2 || ... METHOD_N } LIST
例如:
sub regular_sort {
my $hash = shift;
for (sort { $hash->{$a} <=> $hash->{$b} } keys %$hash) {
print "$_ ";
};
}
sub random_sort {
my $hash = shift;
my %rand = map { $_ => rand } keys %hash;
for (sort { $hash->{$a} <=> $hash->{$b} ||
$rand{$a} <=> $rand{$b} } keys %$hash ) {
print "$_ ";
};
}
sub-regular\u排序{
我的$hash=shift;
对于(排序{$hash->{$a}$hash->{$b}}键%$hash){
打印“$”;
};
}
次随机排序{
我的$hash=shift;
我的%rand=map{$\=>rand}键%hash;
对于(排序{$hash->{$a}$hash->{$b}||
$rand{$a}$rand{$b}}键%$hash){
打印“$”;
};
}
要按值对键进行排序,对具有相同值的键进行随机排序,我看到两种解决方案:
use List::Util qw( shuffle );
use sort 'stable';
my @keys =
sort { $hash{$a} <=> $hash{$b} }
shuffle keys %hash;
use List::Util qw(shuffle);
使用“稳定”排序;
我的@keys=
排序{$hash{$a}$hash{$b}
洗牌键%hash;
或
my@keys=
地图$\u0->[0],
排序{$a->[1]$b->[1]| |$a->[2]$b->[2]}
映射[$\$hash{$\},rand],
密钥%hash;
使用排序“稳定”需要使用code>,以防止排序
破坏洗牌
返回的列表的随机性
以上使用的不是优化的尝试。我见过人们在compare函数本身中使用rand
来尝试实现上述结果,但这样做有两个原因
当使用“行为不端”的比较时,结果被记录为未定义,因此允许sort
返回垃圾、重复元素、缺少元素等
即使sort
不返回垃圾,它也不会是一个公平的排序。将对结果进行加权。您希望对其进行排序,但对具有相同值的键具有随机顺序,对吗?我在for循环中的“sort”之前只尝试了洗牌(来自List::Util),但这显然不起作用,因为它洗牌了整个散列。。乔纳森:是的,那是正确的。等等,你想随机化返回的键的顺序(排序后,仍然保留按值排序),还是在按值排序之前随机化返回的键的顺序?我想随机化返回的键的顺序。@gibson:看下面,这不是最优雅或最流行的,但它的逻辑和多级排序(通过TLP)的示例起作用:)。谢谢大家@M42,如果您想要公平排序,则需要使用使用排序“稳定”代码>。如果没有它,sort
会破坏shuffle
@ikegami的结果,当然你是在开玩笑<代码>洗牌
完成并将列表返回到排序
,然后再使用它的任何值。@TLP,嗯???我不明白你想说什么,但我不开玩笑<代码>perl-E'use sort“\u quicksort”;表示(排序{0}“aa”。“zz”)[0..5];'代码>sm bg mw yy mg RIM您的代码有两个原因。1) 当使用这种“行为不当”的比较时,记录的结果是未定义的,因此允许sort
返回垃圾、重复的元素、缺少的元素等。2)即使sort
不返回垃圾,也不是公平的排序。将权衡结果。我将此修复作为答案发布。@ikegami我看不到对数值比较的引用,也看不到对函数的使用会导致未定义的结果。请提供一些关于这些陈述的文档或解释。它在底部。“比较函数的行为是必需的。如果它返回不一致的结果(例如,有时说$x[1]
小于$x[2]
,有时说相反的结果),则结果定义不清楚。”至于(2)的解释,对不起,我没有详细信息,但我已经看到理论和实际实验都表明,sort{rand}
不会导致随机性
use List::Util qw( shuffle );
use sort 'stable';
my @keys =
sort { $hash{$a} <=> $hash{$b} }
shuffle keys %hash;
my @keys =
map $_->[0],
sort { $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2] }
map [ $_, $hash{$_}, rand ],
keys %hash;