hash whose values are arrays of hashes

D

davidmichaelkarr

I've paged through the docs on arrays and hashes, but I can't find a
clear answer for my situation.

I'm trying to build a hash keyed by a string, where the values are
arrays of hashes. I'll need to add new hashes to the array for
particular keys in the main hash. Later, I'll need to step through the
keys of the main hash and operate on the data in each hash in the
array.

I've tried several variations of this, and it doesn't quite work yet.

Each time I have a new hash to add to the array associated with a key,
I'll need to append the new hash to the end of the array.

I think part of the problem here is that it's not obvious how to add a
hash to the end of an array, without it "opening up" the has into an
array of the keys and values. I think it might require using a
reference to the hash instead, but I'm not sure.

For instance, I figure that the following is a "manual" construction of
a hash holding arrays of hashes, but maybe I'm wrong:

my %testhash = ("abc" => (("xxx" => "yyy"), ("aaa" => "bbb")),
"def" => (("jjj" => "kkk"), ("ppp" =>
"qqq")));

If I try to reference the "abc" key, like this:

print $testhash{"abc"};

it prints "xxx". I'm not certain what that indicates.
 
J

John W. Krahn

I've paged through the docs on arrays and hashes, but I can't find a
clear answer for my situation.

I'm trying to build a hash keyed by a string, where the values are
arrays of hashes. I'll need to add new hashes to the array for
particular keys in the main hash. Later, I'll need to step through the
keys of the main hash and operate on the data in each hash in the
array.

I've tried several variations of this, and it doesn't quite work yet.

Each time I have a new hash to add to the array associated with a key,
I'll need to append the new hash to the end of the array.

I think part of the problem here is that it's not obvious how to add a
hash to the end of an array, without it "opening up" the has into an
array of the keys and values. I think it might require using a
reference to the hash instead, but I'm not sure.

For instance, I figure that the following is a "manual" construction of
a hash holding arrays of hashes, but maybe I'm wrong:

my %testhash = ("abc" => (("xxx" => "yyy"), ("aaa" => "bbb")),
"def" => (("jjj" => "kkk"), ("ppp" =>
"qqq")));

By using parentheses you are creating one list similar to:

my %testhash = qw( abc xxx yyy aaa bbb def jjj kkk ppp qqq );

You need to use [] to create anonymous arrays and {} to create anonymous hashes:

my %testhash = ( abc => [ { xxx => 'yyy' }, { aaa => 'bbb' } ],
def => [ { jjj => 'kkk' }, { ppp => 'qqq' } ] );



John
 
D

davidmichaelkarr

John said:
I've paged through the docs on arrays and hashes, but I can't find a
clear answer for my situation.

I'm trying to build a hash keyed by a string, where the values are
arrays of hashes. I'll need to add new hashes to the array for
particular keys in the main hash. Later, I'll need to step through the
keys of the main hash and operate on the data in each hash in the
array.

I've tried several variations of this, and it doesn't quite work yet.

Each time I have a new hash to add to the array associated with a key,
I'll need to append the new hash to the end of the array.

I think part of the problem here is that it's not obvious how to add a
hash to the end of an array, without it "opening up" the has into an
array of the keys and values. I think it might require using a
reference to the hash instead, but I'm not sure.

For instance, I figure that the following is a "manual" construction of
a hash holding arrays of hashes, but maybe I'm wrong:

my %testhash = ("abc" => (("xxx" => "yyy"), ("aaa" => "bbb")),
"def" => (("jjj" => "kkk"), ("ppp" =>
"qqq")));

By using parentheses you are creating one list similar to:

my %testhash = qw( abc xxx yyy aaa bbb def jjj kkk ppp qqq );

You need to use [] to create anonymous arrays and {} to create anonymous hashes:

my %testhash = ( abc => [ { xxx => 'yyy' }, { aaa => 'bbb' } ],
def => [ { jjj => 'kkk' }, { ppp => 'qqq' } ] );

Ok, then consider this:

my %testhash = {abc => [ {xxx => 'yyy', jjj => 'mmm'}, {aaa => 'bbb',
ccc => 'ddd'} ],
def => [ {jjj => 'kkk', ppp => 'qqq'} ]
};

my @stuff = $testhash{'abc'};
my %hash = $stuff[0];
print "xxx[". $hash{'xxx'} . "]\n";
print "jjj[" . $hash{'jjj'} . "]\n";

Both of these print statements print empty strings for their values.

I thought perhaps two two references should be "$hash{xxx]" and
"$hash{jjj}" instead, but that had no effect. It still appeared to be
empty.
 
J

John W. Krahn

John said:
my %testhash = ("abc" => (("xxx" => "yyy"), ("aaa" => "bbb")),
"def" => (("jjj" => "kkk"), ("ppp" =>
"qqq")));
By using parentheses you are creating one list similar to:

my %testhash = qw( abc xxx yyy aaa bbb def jjj kkk ppp qqq );

You need to use [] to create anonymous arrays and {} to create anonymous hashes:

my %testhash = ( abc => [ { xxx => 'yyy' }, { aaa => 'bbb' } ],
^^^
def => [ { jjj => 'kkk' }, { ppp => 'qqq' } ] );

Ok, then consider this:

my %testhash = {abc => [ {xxx => 'yyy', jjj => 'mmm'}, {aaa => 'bbb',
^^^

You are assigning a single anonymous hash to %testhash. Do you have strict
and warnings enabled?
ccc => 'ddd'} ],
def => [ {jjj => 'kkk', ppp => 'qqq'} ]
};

my @stuff = $testhash{'abc'};

$testhash{'abc'} contains a single scalar value. If that value is a reference
to an array you need to dereference it.

my @stuff = @{$testhash{'abc'}};



perldoc perlreftut
perldoc perlref
perldoc perldsc
perldoc perllol



John
 
J

John Bokma

I've paged through the docs on arrays and hashes, but I can't find a
clear answer for my situation.

I'm trying to build a hash keyed by a string, where the values are
arrays of hashes.


my %example = (

abc => [

{
xxx => 'yyy',
}
{

aaa => 'bbb',
}

]
);

I'll need to add new hashes to the array for
particular keys in the main hash.


push @{ $example{ 'abc' } }, { jjj => 'kkk' };

Later, I'll need to step through the
keys of the main hash and operate on the data in each hash in the
array.

for my $key ( keys %example ) {

for my $hash ( @{ $example{ $key } } ) {

# $hash is now a reference to an element (hash) in
# the array. The reference to this array is a value
# stored in the example hash with key $key.
}
}
Each time I have a new hash to add to the array associated with a key,
I'll need to append the new hash to the end of the array.

perldoc -f push

if $example{ 'abc' } is a reference to an array, then you can derefence
it with @ and use push to add a reference to a hash, i.e.

push @{ $example{ 'abc' } }, { jjj => 'kkk' };


print $example{ 'abc' }[ -1 ]{ 'jjj' };

should give kkk

-1 = last item in array.
I think part of the problem here is that it's not obvious how to add a
hash to the end of an array, without it "opening up" the has into an
array of the keys and values.

So you add a reference to a hash to an array.
I think it might require using a
reference to the hash instead, but I'm not sure.

If you want to eliminate duplicates, not. I assumed you don't want to do
this, and hence used references in the example above, because that comes
closer to an array of hashes.

A tip:

use Data::Dumper;

:
:
:

print Dumper \%example;

this shows how things are stored, wich might come in very handy when
working with complicated datastructures.

As using pen and paper to draw first the data structure :-D.
 
D

david.karr

John said:
I've paged through the docs on arrays and hashes, but I can't find a
clear answer for my situation.

I'm trying to build a hash keyed by a string, where the values are
arrays of hashes.


my %example = (

abc => [
[deleted]
]
);
I'll need to add new hashes to the array for
particular keys in the main hash.

push @{ $example{ 'abc' } }, { jjj => 'kkk' };

When I do something like this:

my %testhash = {abc => [ {xxx => 'yyy', jjj => 'mmm'},
{aaa => 'bbb', ccc => 'ddd'}
],
def => [ {jjj => 'kkk', ppp => 'qqq'} ] };

my @stuff = @{$testhash{'abc'}};

It complains:

"Can't use an undefined value as an ARRAY reference at ..."
So you add a reference to a hash to an array.


If you want to eliminate duplicates, not. I assumed you don't want to do
this, and hence used references in the example above, because that comes
closer to an array of hashes.

I'm not exactly certain what you're recommending here.

For background, my hash of arrays of hashes will be built up
incrementally, processing a set of log files one by one, using a
substring from each line as the key to the main hash, and each entry of
the array keyed by that string represents lines where that substring
was present. The hash in each array entry represents the fields found
in each line.

So, on each line of each file, I have a "my" hash that stores the
fields of the line, including the "key" field. I then get the array of
lines using the same key from the main hash. This array could be empty
if this is the first line with this key value. I then add the new
"line" hash to the array for the main key.

Once I've built up this data structure (and some similar ones), I'll
iterate through the data structures and generate some statistics from
the values found.

Based on this, I don't believe I need to worry about whether I'm
removing duplicates or not, as the "line" hash is created for each line
of each log file.
A tip:

use Data::Dumper;

I'll definitely look at this, once my code compiles :) .
 
P

Paul Lalli

david.karr said:
When I do something like this:

my %testhash = {abc => [ {xxx => 'yyy', jjj => 'mmm'},
{aaa => 'bbb', ccc => 'ddd'}
],
def => [ {jjj => 'kkk', ppp => 'qqq'} ] };

my @stuff = @{$testhash{'abc'}};

It complains:

"Can't use an undefined value as an ARRAY reference at ..."

If you'd enable warnings in your code, Perl would tell you about the
real problem here, rather than just the first truly impossible thing
that happened.

You assigned your hash to have one key with no value. That one key is
a reference to a hash whose keys are 'abc' and 'def'.

Change the outer { } to ( ). And always, yes *always* include the
lines
use strict;
use warnings;
right under the shebang.

Paul Lalli
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Iterating hashes 11
Sum of two arrays 3
having trouble with hash of arrays... 12
hash of hashes 9
Sorting hash of hashes 3
hash 19
hash of arrays 1
Arrays and Hashes 4

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top