2010-03-04 19 views
8

Sto scrivendo uno script che leggerò attraverso i miei ceppi ftpd e generare un hash come segue:Perl: Accedere a rifhash ordinati per valore

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

Come posso accedere a questo hash con le chiavi ordinati per dimensione?

Ho provato questo, ma ottengo un errore non dire una rifhash

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

blahblahblah... 
} 
+0

dopo aver riletto la tua domanda, la soluzione postato funzionerà, ma è necessario cambiare "chiavi% $ stats "a" keys% $$ stats "nel tuo foreach. Questo è il motivo per il tuo "non un errore di hashref" b/c stai cercando di trattare un ref di un hashref come l'hashref stesso. –

+0

Grazie, non avevo capito che era un riferimento a un hashref. Sciocco errore :) – somebody

risposta

14

Il tuo problema non è correlato all'ordinamento ma al modo insolito che hai definito $stats - ovvero, come riferimento a un riferimento di hash.

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

È possibile utilizzare questo:

my $stats = { ... }; 

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

O questo, se proprio deve fare l'arbitro-to-hash-ref cosa:

my $stats = \{ ... }; 

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

Si noti inoltre che probabilmente desidera utilizzare <=> (confronto numerico) anziché cmp (confronto stringa).

4

È possibile passare una funzione per ordinare al fine di ottenere i valori nell'ordine che si desidera.

#!/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'}; 
} 

USCITA:

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

Se si desidera loro ordinati basso al più alto, è sufficiente accendere il $ b e $ una nella funzione sortBySize:

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

La prima riga sembra essere sbagliata. Dovrebbe essere

$stats = { 

Il tuo tentativo soffre di un altro errore di sintassi; è necessario un solo sigillo quando dereferenziazione con ->, e credo che sia meglio astenersi dal hashkeys bareword:

foreach my $user (sort { $stats->{$a}->{'size'} cmp $stats->{$b}->{'size'} } 
         keys %$stats) { 
    # ... 
    } 
Problemi correlati