2011-04-11 75 views
3

我有一個散列引用數組。哈希包含2個鍵,USER和PAGES。這裏的目標是通過散列引用的數組,並保持用戶打印在打印機上的頁面總數(這來自事件日誌)。我從Excel電子表格中提取數據,並使用正則表達式來提取用戶名和頁面。電子表格中有182行,每行包含一個用戶名和他們在該作業上打印的頁數。目前,腳本可以打印每個打印作業(全部182個),其中包含用戶名和打印的頁面,但我希望將其合併,以便顯示:用戶名266(即僅顯示用戶名一次,以及它們打印的總頁數對於整個電子表格,如何在Perl中整合散列?

這裏是我嘗試通過散列引用數組,看看用戶是否已經存在,如果是這樣,+ =該用戶的頁數爲一個新的散列引用數組(a較小的一個),如果不是,然後將用戶添加到新的哈希值裁判數組:

my $criteria = "USER"; 
my @sorted_users = sort { $a->{$criteria} cmp $b->{$criteria} } @user_array_of_hash_refs; 

my @hash_ref_arr; 
my $hash_ref = \@hash_ref_arr; 

foreach my $index (@sorted_users) 
{ 
    my %hash = (USER=>"",PAGES=>""); 
    if(exists $index{$index->{USER}}) 
    { 
     $hash{PAGES}+=$index->{PAGES}; 
    } 
    else 
    { 
     $hash{USER}=$index->{USER}; 
     $hash{PAGES}=$index->{PAGES}; 
    } 
    push(@hash_ref_arr,{%hash}); 
} 

但它給我一個錯誤:

全局符號「%index」需要明確的包名...

也許我的邏輯不是最好的。我應該使用數組嗎?鑑於我的數據的性質,似乎哈希是最好的東西。我只是不知道如何去減少哈希引用數組來獲取用戶名和他們打印的總頁數(我知道我看起來多餘,但我只是想澄清)。謝謝。

回答

2

由於MKB提到的,錯誤是在以下line:

if(exists $index{$index->{USER}}) 

但是,在閱讀您的代碼後,您的邏輯有問題。簡單地更正語法錯誤將不會提供您想要的結果。

我建議在循環中跳過使用臨時散列。只需直接使用結果散列。

例如:

#!/usr/bin/perl 
use strict; 
use warnings; 

my @test_data = (
    { USER => "tom", PAGES => "5" }, 
    { USER => "mary", PAGES => "2" }, 
    { USER => "jane", PAGES => "3" }, 
    { USER => "tom", PAGES => "3" } 
); 

my $criteria = "USER"; 
my @sorted_users = sort { $a->{$criteria} cmp $b->{$criteria} } @test_data; 

my %totals; 

for my $index (@sorted_users) { 
    if (not exists $totals{$index->{USER}}) { 
     # initialize total for this user 
     $totals{$index->{USER}} = 0; 
    } 

    # add to user's running total 
    $totals{$index->{USER}} += $index->{PAGES} 
} 

print "$_: $totals{$_}\n" for keys %totals; 

這將產生以下的輸出:

$ ./test.pl 
jane: 3 
tom: 8 
mary: 2 
+0

美麗。正是我需要的。非常感謝。每個人真的。所有非常有幫助。對此,我真的非常感激。 – 2011-04-11 14:59:57

+2

您不需要在循環中使用'if'語句。 Perl會自動創建一個條目,如果沒有。另外,如果print打印語句看起來更好:'print Dumper \%totals;' – shawnhcorey 2011-04-11 15:31:52

+1

我不明白爲什麼要對輸入進行排序。我的意思是,當然,你已經從原來的問題中複製了它,但它似乎也沒有意義:-) – 2011-04-11 16:04:17

0

誤差來源於此行:

if(exists $index{$index->{USER}}) 

$印記在Perl 5名之後{}意味着你得到一個標值超出散列。沒有名稱%index聲明的散列。我想,你可能只需要添加一個->運營商,所以這個問題行變成了:

if(exists $index->{$index->{USER}}) 

,但不具有數據讓我不確定。

此外,對你使用use strict好,或者你會默默地實例化%index哈希,並想知道爲什麼你的結果沒有任何意義。

+0

你除了做了修復我的錯誤,但並未如預期的輸出。它顯示了所有的打印作業(即每次用戶在文件中出現以及與其關聯的頁面)。所以我的邏輯有些問題。 – 2011-04-11 14:33:53

0
my %total; 
for my $name_pages_pair (@sorted_users) { 
    $total{$name_pages_pair->{USER}} += $name_pages_pair->{PAGES}; 
} 

for my $username (sort keys %total) { 
    printf "%20s %6u\n", $username, $total{$username}; 
} 
+0

我得到了一堆錯誤行:在win32excel.pl第85行使用未初始化的值(+)。但是它確實打印了每個用戶名只有一次,但總共爲0頁。 – 2011-04-11 14:22:25

+0

我用你的打印循環,所以我希望我可以給你們兩個信貸的答案。非常感謝! – 2011-04-11 15:01:17

3
my %totals; 

$totals{$_->{USER}} += $_->{PAGES} for @user_array_of_hash_refs; 

,然後來獲取數據了:

print "$_ : $totals{$_}\n" for keys %totals; 

您可以通過使用排序太:

print "$_ : $totals{$_}\n" for sort { $totals{$a} <=> $totals{$b} } keys %totals;