[英]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.