Perl: Получите доступ к hashref, отсортированному по значению

Я пишу сценарий, это прочитает мои журналы ftpd и генерирует хеш следующим образом:

$stats = \{
            'user1' => {
                        'files' => 281,
                        'size' => '3724251021'
                      },
            'user2' => {
                      'files' => 555,
                      'size' => '7385856997'
                    },
            'user3' => {
                          'files' => 235,
                          'size' => '3716904486'
                        },
            'user4' => {
                       'files' => 578,
                       'size' => '8536026929'
                     }
          };

Как я получаю доступ к этому хешу с ключами, отсортированными по размеру?

Я попробовал это, но я получаю ошибку при высказывании не hashref

foreach my $user (sort { $$stats->{$a}->{size} cmp $$stats->{$b}->{size} } keys %$stats) {

blahblahblah...
}
9
задан Brian Carlton 4 March 2010 в 14:12
поделиться

3 ответа

Ваша проблема связана не с сортировкой, а с необычным способом определения $stats - а именно, как ссылка на хэш-ссылку.

my %hash            =  (a => 1, b => 2);
my $hash_ref        =  {c => 3, d => 4};
my $ref_to_hash_ref = \{e => 5, f => 6};

Вы можете использовать либо это:

my $stats = { ... };

foreach my $user ( 
        sort { $stats->{$a}{size} <=> $stats->{$b}{size} }
        keys %$stats ) {
    ...
}

либо это, если вам действительно нужно сделать ссылку на хэш-ссылку:

my $stats = \{ ... };

foreach my $user (
        sort { $$stats->{$a}{size} <=> $$stats->{$b}{size} }
        keys %$$stats ) {
    ...
}

Заметьте также, что вы, вероятно, хотите использовать <=> (числовое сравнение), а не cmp (строковое сравнение).

16
ответ дан 4 December 2019 в 09:36
поделиться

Вы можете передать функцию для сортировки, чтобы получить значения в том порядке, в котором вы хотите.

#!/usr/bin/perl

use strict;

my $stats = {
            'user1' => {
                          'files' => 281,
                          'size'  => '3724251021'
                       },

            'user2' => {
                          'files' => 555,
                          'size'  => '7385856997'
                       },

            'user3' => {
                          'files' => 235,
                          'size'  => '3716904486'
                       },

            'user4' => {
                          'files' => 578,
                          'size'  => '8536026929'
                       }
          };

foreach my $key (sort sortBySize (keys(%$stats)))
{
     print $key, " => ", $stats->{$key}->{'files'}, " - ",
           $stats->{$key}->{'size'}, "\n";
}

exit;

sub sortBySize
{
    return $stats->{$b}->{'size'} <=> $stats->{$a}->{'size'};
}

ВЫВОД:

user4 => 578 - 8536026929
user2 => 555 - 7385856997
user1 => 281 - 3724251021
user3 => 235 - 3716904486

Если вы хотите, чтобы они отсортировывались от наименьшего к наибольшему, вам просто нужно переключить $ b и $ a в функции sortBySize:

return $stats->{$a}->{'size'} <=> $stats->{$b}->{'size'};
5
ответ дан 4 December 2019 в 09:36
поделиться

Кажется, ваша первая строка ошибочна. Это должно быть

$stats = {

. Ваша попытка страдает другой синтаксической ошибкой; вам нужен только один сигил при разыменовании с помощью -> , и я считаю, что лучше воздержаться от хэш-ключей без пароля:

foreach my $user (sort { $stats->{$a}->{'size'} cmp $stats->{$b}->{'size'} }
                       keys %$stats) {
  # ...
  }
1
ответ дан 4 December 2019 в 09:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: