2012-11-15 66 views
0

我有一個解析Excel文件的Perl腳本,它執行以下操作:它爲列A中的每個值計數,它在列B中具有的元素數量,該腳本如下所示:使用perl對哈希值進行hash散列

use strict; 
use warnings; 
use Spreadsheet::XLSX; 
use Data::Dumper; 
use List::Util qw(sum); 

my $col1 = 0; 
my %hash; 

my $excel = Spreadsheet::XLSX->new('inout_chartdata_ronald.xlsx'); 


my $sheet = ${ $excel->{Worksheet} }[0]; 


$sheet->{MaxRow} ||= $sheet->{MinRow}; 
my $count = 0; 
# Iterate through each row 
foreach my $row ($sheet->{MinRow}+1 .. $sheet->{MaxRow}) { 

# The cell in column 1 
my $cell = $sheet->{Cells}[$row][$col1]; 

if ($cell) { 

    # The adjacent cell in column 2 
    my $adjacentCell = $sheet->{Cells}[$row][ $col1 + 1 ]; 
    # Use a hash of hashes 

    $hash{ $cell->{Val} }{ $adjacentCell->{Val} }++; 

} 
} 
print "\n", Dumper \%hash; 

輸出看起來是這樣的:

$VAR1 = { 
     '13' => { 
       'klm' => 1, 
       'hij' => 2, 
       'lkm' => 4, 
       }, 
     '12' => { 
       'abc' => 2, 
       'efg' => 2 
       } 
    }; 

這個偉大的工程,我的問題是:我如何可以訪問此輸出$ VAR1的要素,以做到:爲值13,KLM + hij = 3並得到如下最終輸出:

$VAR1 = { 
     '13' => { 
       'somename' => 3, 
       'lkm' => 4, 
       }, 
     '12' => { 
       'abc' => 2, 
       'efg' => 2 
       } 
    }; 

所以基本上我想要做的就是循環訪問散列的最後一個哈希,並根據一個唯一鍵訪問它的特定元素,最後完成它們的總和。

任何幫助,將不勝感激。 謝謝

+0

你想要使用什麼鍵的總和?所有的鑰匙?指定的密鑰子集? – Bitwise

+0

是這個總和會影響所有的鍵,13個會有klm + hij,12個也會有klm + hij。我給的例子很糟糕,我很抱歉。在更實際的情況下,我有: $ VAR1 = { '13'=> { 'somename'=> 3, 'LKM'=> 4, }, '12'=> { 'somename'=> 9, 'lkm'=> 6 } }; – salamey

回答

1

我用@do_sum來指出你想做什麼改變。新密鑰在腳本中被硬編碼。請注意,如果子密碼不存在密鑰($found標誌),則不會創建新密鑰。

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

use Data::Dumper; 

my %hash = (
      '13' => { 
        'klm' => 1, 
        'hij' => 2, 
        'lkm' => 4, 
        }, 
      '12' => { 
        'abc' => 2, 
        'efg' => 2 
        } 
      ); 
my @do_sum = qw(klm hij); 

for my $num (keys %hash) { 
    my $found; 
    my $sum = 0; 
    for my $key (@do_sum) { 
     next unless exists $hash{$num}{$key}; 
     $sum += $hash{$num}{$key}; 
     delete $hash{$num}{$key}; 
     $found = 1; 
    } 
    $hash{$num}{somename} = $sum if $found; 
} 

print Dumper \%hash; 
+0

感謝您的幫助,但我想爲我的散列中的所有密鑰執行此操作。我想要一個循環嗎? (我真的剛剛開始學習Perl,感謝您的理解:)) – salamey

+0

@ user1734229:檢查更新。 – choroba

+0

謝謝,這一直很有幫助。 只是另一個問題,我想和其他鍵一樣,就像'@ do_sum',我想要'@ do_sum2'有例如「abc」和「efg」,我的輸出應該像'somename'= > 10,'othername'=> 12.我需要循環訪問@do_sum和'@ do_sum2',我該怎麼做? – salamey

0

這聽起來像你需要了解Perl References,也許Perl Objects這只是對付引用一個很好的方式。

如你所知,Perl有三種基本的數據結構:

  • 標量($foo
  • 陣列(@foo
  • 哈希(%foo

的問題是,這些數據結構只能包含標量數據。也就是說,數組中的每個元素都可以保存一個值,或者散列中的每個鍵都可以保存一個值。

在你的情況%hash是一個散列,其中散列中的每個條目引用另一個散列。例如:

您的%hash已在其中輸入密鑰13。這不包含標量的值,而是對其中包含三個密鑰的另一個散列的引用:klm,hijlkm。 YOu可以通過以下語法參考:

${ hash{13} }{klm} = 1 
${ hash{13} }{hij} = 2 
${ hash{13} }{lkm} = 4 

大括號可能需要也可能不需要。但是,%{ hash{13} }引用散列中包含的$hash{13},所以我現在可以引用該散列的鍵。你可以想象,當你談論數組散列數的散列哈希值時,這會變得更加複雜。幸運的是,Perl包含更簡單的語法:

$hash{13}->{klm} = 1 
%hash{13}->{hij} = 2 
%hash{13}->{lkm} = 4 

閱讀關於散列以及如何操作它們。在熟悉這個之後,你可以開始學習面向對象的Perl,它以更安全的方式處理引用。