2017-02-01 78 views
0

關於如何check if a hash is empty有很多參考。我在以下腳本中嘗試了它們:爲什麼檢查散列是否爲空失敗?

use strict; 
use warnings; 
use Data::Dumper; 
    $Data::Dumper::Sortkeys = 1; 

# Signals come... 
my %items = (
    item_1 => {signal_1 => 'up', 
       signal_2 => 'down', 
       signal_3 => 'up', 
       }, 
    item_2 => {signal_1 => 'down', 
       }, 
    item_3 => {signal_1 => 'up', 
       signal_3 => 'down', 
       signal_4 => 'down', 
       signal_5 => 'down', 
       }, 
); 

# ... and signals go: 
delete $items{'item_2'}->{'signal_1'}; 
# and sometimes all signals are gone from an item: 
print Dumper(\%items); 
# in that case we would like the signal count to show 0 (zero). 
my %signals; 
foreach my $item (sort keys %items){ 
    #$signals{$item} = 0; 
    foreach my $signal (sort keys %{$items{$item}}){ 
    if (not %{$items{$item}}) {print "HERE\n"; $signals{$item} = 0} 
    elsif($items{$item}->{$signal} eq 'up') {$signals{$item}++} 
    elsif($items{$item}->{$signal} eq 'down'){$signals{$item}--} 
    } 
} 
# unfortunately the item disappears completely! 
print Dumper(\%signals); 

看起來迭代器完全跳過了空的散列。我產生正確結果的唯一方法是將每個計數初始化爲零(註釋掉),並讓其通過非空散列進行遞增/遞減。

爲什麼...?

+1

@Toto我認爲這個問題是爲什麼沒有'item_2 => 0'。 – simbabque

+0

@simbabque:好的,我誤解了:( – Toto

+0

)如果有X個鍵要迭代,那麼這個循環有X個迭代,是的,即使X爲零也是如此。你的「解決方法」實際上是正確的處理這種情況。 – ikegami

回答

4

如果散列中沒有鍵,則keys返回空列表()。當您在空列表上迭代foreach時,循環的主體將永遠不會被調用。所以你的print "HERE"永遠不會到達。這是對的。

foreach (()) { 
    print "foo"; 
} 

__END__ 
(no output) 

Perl的自動vivification在爲你散創造價值,當您使用它們的第一次,和值開出爲0,當你對他們做數學。這就是爲什麼你可以在條件內的循環中添加和減去它們。

爲了使它工作,你已經做了正確的事情與你的評論外線。

foreach my $signal (sort keys %{$items{$item}}){ 
    $signals{$item} = 0; 
    if (... 

現在您首先將每個密鑰初始化爲0。如上所述,這也是隱含的,每次都是這樣。