in reply to Why are Hash keys different for the same hash? Confusing.

See my reply here Re^2: Hashes not working as expected

Try this demo

#!perl use Data::Dumper; my %hash = ( a=>{} ); if ( !exists $hash{'a'}{'b'}{'c'} ){}; print Dumper \%hash;

The problem is with exists creating intermediate levels

 foreach my $signalNm (keys %{$lastKnownSigValHRef->{$vcdFile}->{$signalId}}) {
    ### here
    if(!exists $inTimeRangeSignalsH{$vcdFile}{$signalNm}{$signalId}) {
     $sigsNotInTimeRangeH{$vcdFile}{$signalNm}{$signalId} = $lastKnownSigValHRef->{$vcdFile}->{$signalId}->{$signalNm}->{$hierScope}->[0];
    }
  }

I think you can fix it like this

foreach my $signalNm (keys %{$lastKnownSigValHRef->{$vcdFile}->{$signalId}}) {

  if (exists $inTimeRangeSignalsH{$vcdFile}{$signalNm}) {
    if (exists $inTimeRangeSignalsH{$vcdFile}{$signalNm}{$signalId}) {
      next;
    }
  }
  $sigsNotInTimeRangeH{$vcdFile}{$signalNm}{$signalId} 
  = $lastKnownSigValHRef->{$vcdFile}{$signalId}{$signalNm}{$hierScope}[0];

}

Update : Rather than returning variables from your methods you can encapsulate them into the object. For example, replacing the return statement from parseData with

#return(\%lastKnownSigValH, \%scopesHierH, \%scopesH, \%timeRangeH, # \%timeIntervalBasedActivityH, $vcdFile, $timeUnits); $self->{lastKnownSigValH} = \%lastKnownSigValH; $self->{scopesHierH} = \%scopesHierH; $self->{scopesH} = \%scopesH; $self->{timeRangeH} = \%timeRangeH; $self->{timeIntervalBasedActivityH} = \%timeIntervalBasedActivityH; $self->{vcdFile} = $vcdFile; $self->{timeUnits} = $timeUnits;

would allow you to write more readable code like this

#!/usr/bin/perl use strict; use warnings; use diagnostics -verbose; my $vcdFile = $ARGV[0]; my $datObj = Datafile->new(); $datObj->collectSignals($vcdFile); package Datafile; sub new { my $class = shift; my $self = { inTimeRangeSignalsH => {}, sigsNotInTimeRangeH => {}, timeRng => {}, hierScope => {}, }; return bless $self, $class; } sub collectSignals { my $self = shift; my $vcdFileOrig = shift; $self->parseData($vcdFileOrig); if (exists $self->{timeRangeH}{$vcdFile}) { my $timeRng = $self->{timeRangeH}{$vcdFile}{'TIMERANGES'}[-1]; $self->{timeRng} = $timeRng; if (exists $self->{timeIntervalBasedActivityH}{$vcdFile}) { my $hr1 = $self->{timeIntervalBasedActivityH}{$vcdFile}; if (exists $hr1->{$timeRng}) { my $hr2 = $hr1->{$timeRng}; for my $sigId (keys %$hr2) { for my $sigName (keys %{$hr2->{$sigId}}) { for my $scopeNm (keys %{$hr2->{$sigId}{$sigName}}) { if ( ($scopeNm =~ /_TB/) && (exists $hr2->{$sigId}{$sigName}{$scopeNm}{'EXPANDE +DVAL'}) ) { $self->{hierScope} = $scopeNm; my $sigValue = $hr2->{$sigId}{$sigName}{$scopeNm}{'EX +PANDEDVAL'}[-1]; $self->{inTimeRangeSignalsH}{$vcdFile}{$sigName}{$sigI +d}{$timeRng}{$scopeNm} = $sigValue; } } } } } foreach my $signal (keys %{$self->{inTimeRangeSignalsH}{$vcdFile +}}) { print "Line 51 ::Dbg:: $signal $vcdFile\n"; } } } if (exists $self->{lastKnownSigValH}{$vcdFile}) { my $hr1 = $self->{lastKnownSigValH}{$vcdFile}; foreach my $signalId (keys %$hr1) { foreach my $signalNm (keys %{$hr1->{$signalId}}) { if (exists $self->{inTimeRangeSignalsH}{$vcdFile}{$signalNm}){ if (exists $self->{inTimeRangeSignalsH}{$vcdFile}{$signalNm} +{$signalId}){ next; } } #if(!exists $self->{inTimeRangeSignalsH}{$vcdFile}{$signalNm}{ +$signalId}) { $self->{sigsNotInTimeRangeH}{$vcdFile}{$signalNm}{$signalId} = $hr1->{$signalId}{$signalNm}{$self->{hierScope}}[0]; #} } } } my $hr = $self->{inTimeRangeSignalsH}; for my $vcdFile (keys %$hr) { for my $sig (keys %{$hr->{$vcdFile}}) { print "Line 75 ::Dbg:: $sig $vcdFile\n"; } } }

For debugging, it also allows you to dump all the data easily with

use Data::Dump 'pp';
pp $datObj;
poj

Replies are listed 'Best First'.
Re^2: Why are Hash keys different for the same hash? Confusing.
by dsheroh (Monsignor) on Feb 28, 2016 at 09:03 UTC
    The problem is with exists creating intermediate levels
    Note that, if you consider this to be a problem you can install the autovivification module, then specify no autovivification to prevent it:
    #!/usr/bin/env perl use strict; use warnings; use 5.010; no autovivification; use Data::Dumper; my %hash = ( a=>{} ); if ( !exists $hash{'a'}{'b'}{'c'} ){}; print Dumper \%hash;
    Output:
    $VAR1 = { 'a' => {} };
    This is, however, apparently not an option for the OP, due to short-sighted customer requirements and autovivification is an XS module, so using its code independently of the original module would be a bit more involved than just copy/pasting the source.
        Oooh... Nice! That actually solves something that's come up in one of my work projects recently. Thanks!