Re: Hashes of Hashes
- From: "Paul Lalli" <mritty@xxxxxxxxx>
- Date: 29 Dec 2006 08:55:55 -0800
Jason Malburg wrote:
I'm working on a complex data structure with hashes of hashes and
hashes of arrays and I noticed a weird behavior I was hoping someone
could explain. Here's a sample:
$Data{US17}{1}{GROUP} = "STRING";
$Data{US17}{1}{GROUP}{.001} = 5;
$Data{US17}{1}{GROUP}{.002} = 6;
$Data{US17}{1}{GROUP}{.003} = 7;
print "group = $Data{US17}{1}{GROUP}\n";
for my $time (keys %{$Data{US17}{1}{GROUP}}){
print "time = $time $Data{US17}{1}{GROUP}{$time}\n";
}
The output is:
group = STRING
time = 0.002 6
time = 0.003 7
time = 0.001 5
If I swap the order of the declarations, then all of the keys for the
hash under 'GROUP' are wiped out. For example:
$Data{US17}{1}{GROUP}{.001} = 5;
$Data{US17}{1}{GROUP}{.002} = 6;
$Data{US17}{1}{GROUP}{.003} = 7;
$Data{US17}{1}{GROUP} = "STRING";
only produces:
group = STRING
Is this expected behavior? Am I getting lucky in the first instance
with bad syntax that just happens to do what I want?
Yes, that's exactly correct. What you are doing is using "symbolic
references". The first line:
$Data{US17}{1}{GROUP} = "STRING";
assigns the string "STRING" to be the value of the key 'GROUP' in the
hash that is referenced by $Data{US17}{1}. Presuming this hash has no
other key/value pairs already created, the following is an identical
assignment:
%{$Data{US17}{1}} = ("GROUP" => "STRING");
Your next three statements, however, make an assumption that does not
correlate to this first one:
$Data{US17}{1}{GROUP}{.001} = 5;
$Data{US17}{1}{GROUP}{.002} = 6;
$Data{US17}{1}{GROUP}{.003} = 7;
These are now assigning the numbers 5, 6, and 7, to be values of the
keys ".001", ".002", and ".003" (respectively) of the hash that is
referenced by $Data{US17}{1}{GROUP}.
Do you see the conflict? You are making an assmption that
$Data{US17}{1}{GROUP} is a reference to a hash. But one statement
earlier, you said that $Data{US17}{1}{GROUP} is a string -
specifically, "STRING". So you're trying to say:
%{$Data{US17}{1}{GROUP}} = ( .001 => 5, .002 => 6, .003 => 7);
But because $Data{US17}{1}{GROUP} is a string, this is the same thing
as:
%{STRING} = (.001 => 5, .002 => 6, .003 => 7);
That is, Perl created a completely new variable, %STRING, and assigned
your hash to that. This is known as a "symbolic reference" - using the
value of one variable as the name of another variable. If you print
out, for example, $STRING{.001} you will see the value 5.
When you did it the other way around:
$Data{US17}{1}{GROUP}{.001} = 5;
$Data{US17}{1}{GROUP}{.002} = 6;
$Data{US17}{1}{GROUP}{.003} = 7;
these three statements make $Data{US17}{1}{GROUP} into a hash reference
automatically - through a process known as "autovivification". If an
undefined value (such as a previously non-existent value of a hash) is
used as a hash reference, a real hash reference springs into existence.
But then immediately after implicitly creating this hash reference,
you do:
$Data{US17}{1}{GROUP} = "STRING";
Which changes the value of $Data{US17}{1}{GROUP}. It is no longer that
hash reference you created. Now it's a simple string. Therefore, the
hash that was previously referenced here simply goes away. And you
lose the three key/value pairs you'd added to it.
Symbolic references are generally a very bad idea (see: perldoc -q
"variable name"). If you put the line:
use strict;
at the top of your program, Perl will prevent you from using a symbolic
reference. This is a good thing.
As for how to solve your original problem while avoiding hash
references, you'll have to rethink your data structure a bit. You
can't have $Data{US17}{1}{GROUP} be both a string and a hash reference.
I would suggest leaving it a hash reference, and possibly adding
another level of indirection:
$Data{US17}{1}{GROUP}{string_val} = "STRING";
$Data{US17}{1}{GROUP}{num_vals}{.001} = 5;
$Data{US17}{1}{GROUP}{num_vals}{.002} = 6;
$Data{US17}{1}{GROUP}{num_vals}{.003} = 7;
Hope this helps,
Paul Lalli
.
- References:
- Hashes of Hashes
- From: Jason Malburg
- Hashes of Hashes
- Prev by Date: Re: Hashes of Hashes
- Next by Date: Re: Hashes of Hashes
- Previous by thread: Re: Hashes of Hashes
- Next by thread: Re: Hashes of Hashes
- Index(es):
Relevant Pages
|