Perl: доступ к хэш-памяти, отсортированной по значению - PullRequest
8 голосов
/ 04 марта 2010

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

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

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

Я пробовал это, но я получаю сообщение об ошибке, не говоря о хэш-адресе

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

blahblahblah...
}

Ответы [ 3 ]

15 голосов
/ 04 марта 2010

Ваша проблема связана не с сортировкой, а с необычным способом, который вы определили $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 ) {
    ...
}

Или вот, если вам действительно нужно выполнить функцию ref-to-hash-ref:

my $stats = \{ ... };

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

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

4 голосов
/ 04 марта 2010

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

#!/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'};
1 голос
/ 04 марта 2010

Ваша первая строка кажется ошибочной. Должно быть

$stats = {

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

foreach my $user (sort { $stats->{$a}->{'size'} cmp $stats->{$b}->{'size'} }
                       keys %$stats) {
  # ...
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...