繁体   English   中英

按值对数组的哈希排序

[英]sort hash of array by value

我试图在 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.5bcd027df10f27bf9a880ce7bc1dd924'
===
B:
0x00000008 => '0x00000008, atgdb003f_avg01, hdisk10, atgdb003f_data, atgdb003f_data.5bcd027df10f27bf9a880ce7bc1dd924, atgdb003f_ovg01, hdisk96, atgdb003f_pvg01, hdisk68, atgdb003f_rvg01, hdisk8'

__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 out ### 
            ###0x00000008,atgdb003f_avg01,hdisk10,atgdb003f_ovg01,hdisk96,atgdb003f_pvg01,hdisk68,atgdb003f_rvg01,hdisk8,vtscsi0,atgdb003f_data.5bcd027df10f27bf9a880ce7bc1dd924
        ###0x00000008,atgdb003f_avg01,hdisk10,atgdb003f_data,atgdb003f_data.5bcd027df10f27bf9a880ce7bc1dd924,atgdb003f_ovg01,hdisk96,atgdb003f_pvg01,hdisk68,atgdb003f_rvg01,hdisk8

更新arrayrefs(哈希值)毕竟有多个元素,需要排序。 然后

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

或者,更有效的 (在语句修饰符形式中,噪音较小但可能不太清晰)

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

排序默认使用字典序排序,被通缉。

键需要按数字排序,但请注意,虽然我们可以重写数组以使其排序,但哈希并非如此,哈希本质上是无序的。 我们当然可以打印排序

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

如果键不是数字,这将发出警告。

在我在三台不同机器上的基准测试中提高了 56% – 60%,同时使用 v5.16 和 v5.30.0


原帖

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

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

请参阅perlop 中 Equality 运算符下的cmp运算 它需要按字符串进行比较的标量(因此尝试使用问题中的数组进行排序是错误的,因为cmp会获取这些数组的长度进行排序!)


在我的理解你的哈希排序就像

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

其中每个值都是一个数组引用,只有一个元素。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM