Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
perl:洗牌值排序哈希?_Perl_Sorting_Hash - Fatal编程技术网

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;

使用排序“稳定”,以防止
排序
破坏
洗牌
返回的列表的随机性


以上使用的不是优化的尝试。我见过人们在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;