Perl:对多维哈希

时间:2016-02-26 00:21:18

标签: perl data-structures hash subroutine

我有一个看起来像这样的子程序:

...

sub UserLogins { 
  my %loginData; 
  my @logins = qx(last) or die;

  foreach my $row (@logins) {
    if ( $row=~ /^(\w+)\s+/ and (("$1" ne "reboot") and ("$1" ne "wtmp")) ) {
      $loginData{$1}{"logins"}++; 
    }
  }

return \%loginData
}

...

在主脚本中使用此子例程,我得到以下输出:

...

$VAR1 = {
     'user1' => {
             'oldpassword' = 0,
             'filesize' => '14360',
             'logins' => 1
      },
      'user2' => {
             'oldpassword' = 0,
             'filesize' => '1220',
             'logins' => 15
      },
      'user3' => {
             'oldpassword' = 1,
             'filesize' => '1780',
             'logins' => 7
      }
}

...

我想知道如何对%loginData哈希进行排序,以便首先打印具有最大登录次数的用户(在本例中为user2,user3,user1)。

我也尝试过以这种方式对值进行排序:

foreach my $test_sort (sort {$a <=> $b} values %loginData) {
    say $test_sort;
}

但是这个功能根本不起作用。

我尝试过的另一件事并没有奏效:

print "$_\n" foreach sort {$loginData{$b}->{logins} <=> $loginData{$a}->{logins}} keys %loginData;

更新

此功能确实有效,但显示错误按摩:

print "$_\n" foreach sort {$userData{$b}->{'logins'} <=> $userData{$a}->{'logins'}} keys %userData;

错误:

Use of uninitialized values in numeric comparison (<=>)

2 个答案:

答案 0 :(得分:2)

这是一个规范的解决方案,用于根据值的属性(在本例中为logins)以某种顺序访问哈希元素:

for (sort { $loginData{$b}->{logins} <=>  $loginData{$a}->{logins} } keys %loginData)
{
    ... 
}

请注意$b$a的反转以实现反向排序(大多数登录首先)。

答案 1 :(得分:0)

您无法对哈希进行排序。来自Perl文档:

  

哈希条目以明显随机的顺序返回。

您可以计算按照您喜欢的顺序索引哈希的键列表。

这样的事情:

use Data::Dumper;

our $hash = {
     'user1' => {
             'oldpassword' => 0,
             'filesize' => '14360',
             'logins' => 1
      },
      'user2' => {
             'oldpassword' => 0,
             'filesize' => '1220',
             'logins' => 15
      },
      'user3' => {
             'oldpassword' => 1,
             'filesize' => '1780',
             'logins' => 7
      }
};

sub KeysByLogins {
  my $hash = shift;
  map { $_->[1] }
  sort { $a->[0] <=> $b->[0] }
  map { [ $hash->{$_}->{logins}, $_ ] } keys %$hash;
}

foreach my $key (KeysByLogins($hash)) {
  print Data::Dumper->Dump([$hash->{$key}], [$key]) . "\n";
}

则...

$ perl foo.pl
$user3 = {
           'oldpassword' => 1,
           'logins' => 7,
           'filesize' => '1780'
         };

$user2 = {
           'filesize' => '1220',
           'logins' => 15,
           'oldpassword' => 0
         };

$user1 = {
           'filesize' => '14360',
           'logins' => 1,
           'oldpassword' => 0
         };