CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Problem with hash of hash of hashes

 



bulrush
User

Dec 29, 2016, 6:07 AM

Post #1 of 4 (1174 views)
Problem with hash of hash of hashes Can't Post

I need to write a subroutine, because this thing I'm doing is done several times in my program, and the subroutine has to do a lot of error checking before it adds a value to a 3d hash (hash of hash of hashes).

The value of $hoh{one}{two}{three} is actually a scalar, multiple values separated by a tab. So my subroutine adds a numeric value to whatever position is needed in the hash value.

I've done some googling and it looks like my code is correct compared to some examples, but I still get an error when I do

Code
perl -c pgm.pl

. The error is: "Global symbol %href requires explicit package name".

I've tried several different notations including using $href->{key1}->{key2}->{key3} but also had problems with that.

Can anyone help me? The complete, mini program showing the error is here: http://pastebin.com/4efDzd6Y

I want to use an in-memory hash because DBM::Deep takes far too long for my purposes. In the loop that populates my 3d hash, I'm processing 10,000 records from a database.

I don't use hash of hashes much so I would greatly appreciate some help. Thank you. :)
-----


(This post was edited by bulrush on Dec 29, 2016, 6:15 AM)


FishMonger
Veteran / Moderator

Dec 29, 2016, 7:37 AM

Post #2 of 4 (1167 views)
Re: [bulrush] Problem with hash of hash of hashes [In reply to] Can't Post

Change:

Code
%{$href{$pkk1}{$pkk2}{$pkk3}}

To:

Code
%{$href->{$pkk1}{$pkk2}{$pkk3}}



BillKSmith
Veteran

Dec 29, 2016, 8:08 AM

Post #3 of 4 (1165 views)
Re: [bulrush] Problem with hash of hash of hashes [In reply to] Can't Post

Your problem has almost nothing to do with multi-dimensional hashes. You do not understand how to dereference a reference to a hash.

Your offending code implies that you have a multi-dimensional hash in your subroutine. The values of this hash are references. The error message correctly tells you that no such hash is declared. Of course it is not declared because that is not at all what you intend.

If I correct the syntax for you, you will not learn a thing. Instead, I refer you to the document perlreftut (in perldoc). The section "Using References" explains it better than I can. As it points out, rule 1 always works. It would solve your problem.

The remainder of the document discusses alternates which apply in special cases. At least one of these would be better for your case. It is still important to learn to use rule 1. You can then understand the others as a "short-hand" notation.

If your rule 1 solution does not work, show us how you tried to apply the rule.
Good Luck,
Bill


BillKSmith
Veteran

Jan 2, 2017, 6:16 AM

Post #4 of 4 (1145 views)
Re: [BillKSmith] Problem with hash of hash of hashes [In reply to] Can't Post

Your subroutine can be much simpler if your hash contains a reference to your array @a rather than a join of its elements because you can access individual elements. Note the syntax to dereference the hash reference. The change to test the keys separately is not really necessary, but it avoids the side effect of autovivification.

Your main program should work with no change (except for print). I have changed it only to set up the test case described in your comments.

Code
use strict; 
use warnings;

my $SEP = "\t";
$SEP = "<TAB>"; # Make tab visible in example
$" = $SEP;
my %emphrshash;
my $empid = 'one';
my $actcode = 'two';
my $job = 'three';
my $esthrs;
my $z;

# Set pos 0
$esthrs = .1;
$z = hashadd3dpos2( \%emphrshash, $empid, $actcode, $job, 0, $esthrs );


# Set pos 1
$esthrs = 5.0;
$z = hashadd3dpos2( \%emphrshash, $empid, $actcode, $job, 1, $esthrs );
print "Old Value: @{$emphrshash{$empid}{$actcode}{$job}}\n";

# Update pos 1
$esthrs = 10.0;
$z = hashadd3dpos2( \%emphrshash, $empid, $actcode, $job, 1, $esthrs );
print "New Value: @{$emphrshash{$empid}{$actcode}{$job}}\n";

exit 0; # Exit main pgm.

###########################################################################
sub hashadd3dpos2 {
my ( $href, $pkk1, $pkk2, $pkk3, $ppos, $pval ) = @_;
die "Invalid data for ($pkk1, $pkk2, $pkk3, $ppos)\n" if !valid($pval);

if ( !exists $href->{$pkk1}
or !exists $href->{$pkk1}{$pkk2}
or !exists $href->{$pkk1}{$pkk2}{$pkk3} )
{
$href->{$pkk1}{$pkk2}{$pkk3} = [0,0];
}

$href->{$pkk1}{$pkk2}{$pkk3}[$ppos] += $pval;

return $pval; # hashadd3dpos
}

sub valid {return 1} # Validation of $pval goes here


OUTPUT:
Old Value: 0.1<TAB>5
New Value: 0.1<TAB>15

Good Luck,
Bill

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives