按值对数组进行散列排序

问题描述 投票:1回答:1

我正在尝试按HoA中的值排序,其中key => [a,b,c]我想按字母顺序排序,并且尝试阅读并没有成功。我认为是逗号,但请帮忙!以下是一个简短的摘要。原始数据与数据转储相对于CLI的显示方式完全相同。我必须使用某种定界符,否则cli输出是乏味的!谢谢!

use strict;
use warnings;

my ( $lsvm_a,$lsvm_b,%hashA,%hashB );
my $vscincludes  = qr/(^0x\w+)\,\w+\,\w+.*/;  #/

open (LSMAP_A, "-|", "/usr/ios/cli/ioscli lsmap -vadapter vhost7 -field clientid vtd backing -fmt ," ) or die $!;
while ($lsvm_a = (<LSMAP_A>)) {
     chomp($lsvm_a);
     next unless $lsvm_a =~ /$vscincludes/;
     @{$hashA{$1}} = (split ',', $lsvm_a);
}

open (LSMAP_B, "-|", "/usr/sbin/clcmd -m xxxxxx /usr/ios/cli/ioscli lsmap -vadapter vhost29 -field clientid vtd backing -fmt ," ) or die $!;
while ($lsvm_b = (<LSMAP_B>)) {
     chomp($lsvm_b);
     next unless $lsvm_b =~ /$vscincludes/;
     push @{$hashA{$1}}, (split ',', $lsvm_b);
}


print "\n\nA:";
for my $key ( sort { $hashA{$a} cmp $hashA{$b} } keys %hashA ) {
    print "$key => '", join(", ", @{$hashA{$key}}), "'\n";
}
##
print "===\nB:";
foreach my $key ( sort { (@{$hashB{$a}}) cmp (@{$hashB{$b}}) } keys %hashB ) {
    print "$key ==> @{$hashB{$key}}\n";
}

print "\n\n__DATA_DUMPER__\n\n";
use Data::Dumper; print Dumper \%hashA; print Dumper \%hashB;

输出

A:0x00000008 =>'0x00000008,atgdb003f_avg01,hdisk10,atgdb003f_ovg01,hdisk96,atgdb003f_pvg01,hdisk68,atgdb003f_rvg01,hdisk8,vtscsi0,atgdb003f_data.5bcd027df10f7bc9a924===B:0x00000008 =>'0x00000008,atgdb003f_avg01,hdisk10,atgdb003f_data,atgdb003f_data.5bcd027df10f27bf9a880ce7bc1dd924,atgdb003f_ovg01,hdisk96,atgdb003f_pvg01,hdisk_68,atgdb003__DATA_DUMPER__$ VAR1 = {'0x00000008'=> ['0x00000008','atgdb003f_avg01','hdisk10','atgdb003f_ovg01','hdisk96','atgdb003f_pvg01','hdisk68','atgdb003f_rvg01','hdisk8','vtscsi0','atgdb003f_data.5bcd027df10f27bf9a880ce7bc1dd924']};$ VAR1 = {'0x00000008'=> ['0x00000008','atgdb003f_avg01','hdisk10','atgdb003f_data','atgdb003f_data.5bcd027df10f27bf9a880ce7bc1dd924','atgdb003f_ovg01','hdisk96','atgdb003f_pvg01','hdisk68','atgdb003f_rvg01','hdisk8']};### CLI输出###### 0x00000008,atgdb003f_avg01,hdisk10,atgdb003f_ovg01,hdisk96,atgdb003f_pvg01,hdisk68,atgdb003f_rvg01,hdisk8,vtscsi0,atgdb003f_data.5bcd027df10f27bf9a880ce7b### 0x00000008,atgdb003f_avg01,hdisk10,atgdb003f_data,atgdb003f_data.5bcd027df10f27bf9a880ce7bc1dd924,atgdb003f_ovg01,hdisk96,atgdb003f_pvg01,hdisk68,atgdb003f_rv
arrays perl sorting hash
1个回答
3
投票

Update毕竟,arrayrefs(哈希值)具有多个元素,需要进行排序。然后

for my $key (keys %h) { @{$h{$key}} = sort @{$h{$key}} }

或更有效地(并且为statement modifier形式,具有较少的噪音但可能不太清晰)

$h{$_} = [ sort @{$h{$_}} ] for keys %h;

[sort默认情况下根据需要使用字典顺序排序。

键希望按数字进行排序,但是请注意,尽管我们可以重写数组以使它们进行排序,但是对于哈希来说并不是这样,哈希本质上是无序的。我们当然可以打印排序

foreach my $k (sort { $a <=> $b } keys %h) { ... } 

如果键不是数字,则会发出警告。

在v5.16和v5.30.0的三台不同机器上,按我的基准分别为56%– 60%


原始帖子

我认为您需要对一个具有arrayref作为值的哈希进行排序,从而该arrayref具有单个元素。然后排序,首先,元素

foreach my $key ( sort { $hashB{$a}->[0] cmp $hashB{$b}->[0] } keys %hashB ) {
    print "$key ==> @{$hashB{$key}}\n";
}

请参见cmp下的Equality operators in perlop运算符。它需要标量,并按字符串进行比较(因此,尝试从问题中对数组进行排序是错误的,因为cmp将获得要排序的那些数组的长度!)


据我了解,您要排序的哈希像

$VAR1 = {
    '0x00000008' => [ 'atgdb003f_avg01,hdisk10,atgdb003f_ovg01,...' ],
    ...
}

其中每个值是一个只有一个元素的arrayref。

© www.soinside.com 2019 - 2024. All rights reserved.