Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.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,我想对一个散列进行排序,它实际上有一个散列作为值。例如: my %hash1=( field1=>"", field2=>"", count=>0, ); my %hash2; $hash2{"asd"}={%hash1}; 我在%hash2中插入了很多散列,它们的计数值不同%hash2 如何根据hash1的计数值对%hash1进行排序 有没有一种方法不需要手动实现快速排序,例如使用Perl的排序函数?my@hash1s=sort{$a->{count}$b

我想对一个散列进行排序,它实际上有一个散列作为值。例如:

my %hash1=(
   field1=>"",
   field2=>"",
   count=>0,
);
my %hash2;
$hash2{"asd"}={%hash1};
我在
%hash2
中插入了很多散列,它们的计数值不同
%hash2

如何根据
hash1
的计数值对
%hash1
进行排序

有没有一种方法不需要手动实现快速排序,例如使用Perl的排序函数?

my@hash1s=sort{$a->{count}$b->{count}}值%hash2;
my @hash1s = sort {$a->{count} <=> $b->{count}} values %hash2;

如果您想从hash2中的值中获得按计数排序的哈希列表(如hash1),这可能会有帮助:

@sorted_hash1_list = sort sort_hash_by_count_key($a, $b) (values (%hash2);


# This method can have any logic you want
sub sort_hash_by_count_key {
    my ($a, $b) = @_;
    return $a->{count} <=> $b->{count};
}
@sorted\u hash1\u list=按\u count\u键($a,$b)(值(%hash2))排序\u hash\u;
#此方法可以具有您想要的任何逻辑
子排序\u哈希\u按\u计数\u键{
我的($a$b)=;
返回$a->{count}$b->{count};
}
有关排序在Perl中如何工作的上下文,请参阅

这里有一个例子,试着让人可读,而不是说英语

#!/usr/bin/perl
# Sort Hash of Hashes by sub-hash's element count.
use warnings;
use strict;


my $hash= {
            A=>{C=>"D",0=>"r",T=>"q"}
           ,B=>{}
           ,C=>{E=>"F",G=>"H"}
          };

sub compareHashKeys {0+(keys %{$hash->{$a}}) <=> 0+(keys %{$hash->{$b}}) }

my @SortedKeys = sort compareHashKeys keys %{$hash};
print join ("," , @SortedKeys) ."\n";
!/usr/bin/perl
#按子哈希的元素计数对哈希进行排序。
使用警告;
严格使用;
我的$hash={
A=>{C=>“D”,0=>“r”,T=>“q”}
,B=>{}
,C=>{E=>“F”,G=>“H”}
};
子比较hashkeys{0+(keys%{$hash->{$a}})0+(keys%{$hash->{$b})}
my@SortedKeys=sort compareHashKeys%{$hash};
打印联接(“,”,@SortedKeys)。“\n”;
从中,对的答案包含了编写代码所需的大部分信息

您可能还想看看学习Perl中有关排序的章节

Chris有一个非常好的答案,尽管我讨厌这样使用
。做同样事情的一个更熟悉的方法是遍历顶级散列的键,但按第二级键排序:

my @sorted_hashes = 
    sort { $hash2->{$a}{count} <=> $hash2->{$b}{count} } 
    keys %hash2;
不过,我们可以在sort()块中获得更多的想象力。我们不需要比较键,而是可以用它们计算一个值,并将该值用作比较

例如,为了使报表顺序不区分大小写,我们使用双引号字符串中的\L序列将所有内容都设置为小写。然后,sort()块比较小写值以确定键的放置顺序

my @keys = sort { "\L$a" cmp "\L$b" } keys %hash;
注意:如果计算很昂贵或者散列包含很多元素,您可能需要查看Schwartzian变换来缓存计算结果

如果我们想改为按散列值排序,我们使用散列键来查找它。我们仍然会得到一个键列表,但这次它们是按其值排序的

my @keys = sort { $hash{$a} <=> $hash{$b} } keys %hash;
my@keys=sort{$hash{$a}$hash{$b}}keys%hash;
如果散列值相同,我们可以对散列键进行二次排序

my @keys = sort {
    $hash{$a} <=> $hash{$b}
        or
    "\L$a" cmp "\L$b"
    } keys %hash;
my@keys=sort{
$hash{$a}$hash{$b}
或
\L$a“cmp”\L$b
}密钥%hash;
按数字使用和字符串使用进行排序

# sort by the numeric count field on inner hash
#
foreach my $key (sort {$hash2{$a}->{'count'} <=> $hash2{$b}->{'count'}} keys %hash2) {
   print $key,$hash2{$key}->{'count'},"\n";
}

# sort by the string field1 (or field2) on the inner hash
#
foreach my $key (sort {$hash2{$a}->{'field1'} cmp $hash2{$b}->{'field1'}} keys %hash2) {
   print $key,$hash2{$key}->{'field1'},"\n";
}
#按内部哈希上的数字计数字段排序
#
foreach my$键(排序{$hash2{$a}->{'count'}$hash2{$b}->{'count'}}}键%hash2){
打印$key,$hash2{$key}->{'count'},“\n”;
}
#按内部哈希上的字符串field1(或field2)排序
#
foreach my$key(排序{$hash2{$a}->{'field1'}cmp$hash2{$b}->{'field1'}}}键%hash2){
打印$key、$hash2{$key}->{'field1'},“\n”;
}
要颠倒顺序,只需交换$a和$b即可:

# sort by the numeric count field on inner hash
#
foreach my $key (sort {$hash2{$a}->{'count'} <=> $hash2{$b}->{'count'}} keys %hash2) {
   print $key,$hash2{$key}->{'count'},"\n";
}

# sort by the string field1 (or field2) on the inner hash
#
foreach my $key (sort {$hash2{$a}->{'field1'} cmp $hash2{$b}->{'field1'}} keys %hash2) {
   print $key,$hash2{$key}->{'field1'},"\n";
}
#按内部哈希上的数字计数字段排序
#
foreach my$键(排序{$hash2{$a}->{'count'}$hash2{$b}->{'count'}}}键%hash2){
打印$key,$hash2{$key}->{'count'},“\n”;
}
#按内部哈希上的字符串field1(或field2)排序
#
foreach my$key(排序{$hash2{$a}->{'field1'}cmp$hash2{$b}->{'field1'}}}键%hash2){
打印$key、$hash2{$key}->{'field1'},“\n”;
}

你的意思是想从hash2中的值中获得按计数排序的哈希列表(如hash1)?是的,Jagmal这意味着我想根据$hash2{“asd”}{count}进行排序。你的意思是说“sort\&sort\u hash\u by\u count\u key,values%hash2”而不是你当前拥有的值吗?我尝试了这种方法,但得到了以下警告:[警告]:在数字比较()中使用未初始化值。在代码段中,对于我的答案和我对你的答案的注释,在测试时为我工作(即使使用-w和“Use strict”)。你会收到该警告,因为你的一个或多个散列没有“count”键的值。如果你想将它们计为0,你可以执行sort{($a->{count}| | 0)($b->{count}| | 0}值%hash2;否我所有的计数值都有0作为默认值。但在我的生产代码中,键的名称不是count,而是total,而是排序算法按升序排序,我需要按降序排序。@holydiver:使用$b->{count a->{count进行降序排序(即交换a和b)。0+应该强制将值转换为数字,但是,它已经这样做了,因此0+实际上是多余的。:-PWell,从cmp生成的值或已经是数字的值,是-1、0或1。数据是什么并不重要。sort()需要-1、0或1来决定如何排序。正如Chris指出的,我将0+放在那里,以将keys数组强制转换为标量(从而保持数组的长度)。显然已经这样做了。我将继续这样做,因为在重新读取代码时,我会很明显地看到预期会发生什么。YMMD
# sort by the numeric count field on inner hash
#
foreach my $key (sort {$hash2{$a}->{'count'} <=> $hash2{$b}->{'count'}} keys %hash2) {
   print $key,$hash2{$key}->{'count'},"\n";
}

# sort by the string field1 (or field2) on the inner hash
#
foreach my $key (sort {$hash2{$a}->{'field1'} cmp $hash2{$b}->{'field1'}} keys %hash2) {
   print $key,$hash2{$key}->{'field1'},"\n";
}