2010-03-04 22 views
8

Tôi đang viết một kịch bản mà sẽ đọc qua các bản ghi ftpd của tôi và tạo ra một băm như sau:Perl: Truy cập một hashref được sắp xếp theo giá trị

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

Làm thế nào để truy cập băm này với các phím được sắp xếp theo kích thước?

tôi đã cố gắng này, nhưng tôi nhận được một lỗi nói rằng không phải là một hashref

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

blahblahblah... 
} 
+0

Sau khi đọc câu hỏi của bạn, giải pháp mà bạn đã viết sẽ làm việc, nhưng bạn cần phải thay đổi "chìa khóa% $ stats "to" keys% $$ stats "trong foreach của bạn. Đây là lý do cho bạn "không phải là một lỗi hashref" b/c bạn đang cố gắng để điều trị một ref đến một hashref như hashref chính nó. –

+0

Cảm ơn, tôi đã không nhận ra đó là một ref cho một hashref. Lỗi lầm ngớ ngẩn :) – somebody

Trả lời

14

Vấn đề của bạn không liên quan đến phân loại nhưng theo cách khác thường bạn đã xác định $stats - cụ thể là, như tham chiếu tham chiếu băm.

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

Bạn có thể sử dụng một trong hai điều này:

my $stats = { ... }; 

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

Hoặc này, nếu bạn thực sự phải làm ref-to-băm-ref điều:

my $stats = \{ ... }; 

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

Cũng lưu ý rằng bạn có thể muốn sử dụng <=> (so sánh số) thay vì cmp (so sánh chuỗi).

4

Bạn có thể vượt qua một chức năng để sắp xếp theo thứ tự để có được các giá trị theo thứ tự bạn muốn.

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

OUTPUT:

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

Nếu bạn muốn họ được sắp xếp thấp nhất đến cao nhất, bạn chỉ cần chuyển đổi $ b, $ một trong hàm sortBySize:

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

Dòng đầu tiên của bạn có vẻ bị nhầm lẫn. Nó phải là

$stats = { 

Nỗ lực của bạn bị lỗi cú pháp khác; bạn chỉ cần một sigil duy nhất khi dereferencing với ->, và tôi tin rằng nó là tốt hơn để tránh hashkeys bareword:

foreach my $user (sort { $stats->{$a}->{'size'} cmp $stats->{$b}->{'size'} } 
         keys %$stats) { 
    # ... 
    } 
Các vấn đề liên quan