HoHoH (hash of HoH's)

A

Aaron DeLoach

Hi All,

I have a file that contains either a hash, or a HoH on each line. I am
creating sub that will read the file and return ONE hash containing all the
other hashes (as sub-hashes?). This way I can access each of the
hashes/HoH's "through" the returned hash. Whew... I'm all hashed out!

I need some direction on how to build the "return" hash from the file
contents.

Regards,
Aaron
 
A

Anno Siegel

Aaron DeLoach said:
Hi All,

I have a file that contains either a hash, or a HoH on each line.

A text file doesn't contain hashes, it contains text. How do you extract
a hash (of hashes) from each line?

That some of the hashes are actually hashes of hashes makes no essential
difference.
I am
creating sub that will read the file and return ONE hash containing all the
other hashes (as sub-hashes?). This way I can access each of the
hashes/HoH's "through" the returned hash. Whew... I'm all hashed out!

To collect the resulting hashes in another hash, you need a key (a string)
together with each hash. How do you extract that?

Otherwise, the best you can do is an array of hashes, one for each line
read.
I need some direction on how to build the "return" hash from the file
contents.

There are lots of possibilities. Which one is best would depend on details
of your data structure that you haven't disclosed.

Supposing there are functions get_hash and get_key which extract the
hash and the key from each line, this builds the super-hash (untested):

my %super;
%{ $super{ get_key( $_)}} = get_hash( $_) while <INPUT>;

Anno
 
A

Aaron DeLoach

Anno Siegel said:
A text file doesn't contain hashes, it contains text. How do you extract
a hash (of hashes) from each line?

I create the hash from different data into a 'string' representation of a
hash and write it to the file. I extract them using the 'eval' function on
each line of the text file.
That some of the hashes are actually hashes of hashes makes no essential
difference.

I didn't think it did. However, when trying to create a 'main' hash of the
hashes (eval-ed strings) in the text file I need a 'key' name from the hash
name. That's where the problem lies (I think).
To collect the resulting hashes in another hash, you need a key (a string)
together with each hash. How do you extract that?
?..


Otherwise, the best you can do is an array of hashes, one for each line
read.

That's whats created when I grep the file contents. Now i want to creata a
'main' hash containing each of the other hashes.
There are lots of possibilities. Which one is best would depend on details
of your data structure that you haven't disclosed.

Supposing there are functions get_hash and get_key which extract the
hash and the key from each line, this builds the super-hash (untested):

my %super;
%{ $super{ get_key( $_)}} = get_hash( $_) while <INPUT>;

I don't understand (forgive me).

Aaron
 
A

Aaron DeLoach

Michal Wojciechowski said:
[...]
I need some direction on how to build the "return" hash from the
file contents.

See 'perldoc perldsc' for examples on HoH's and more sophisticated
data structures. It includes an example of reading the file contents
into a HoH that you could possibly adapt to your needs.

There are also great examples in the Programming Perl book I use. But I
still don't know how to creata a hash of existing hashes.
 
B

Bob Walton

Aaron said:
....


There are also great examples in the Programming Perl book I use. But I
still don't know how to creata a hash of existing hashes.


Well, assuming you have your "line hash" in %linehash, then you can put
a reference to that hash as the value of a "big hash" as follows:

$bighash{'line'.$.}=\%linehash;

Make sure you wipe out %linehash prior to processing every line, or you
will end up with references to *the same hash* in every element of
%bighash. One way to do that would be like:

use strict;
use warnings;
my %bighash;
while(<DATA>){
my %linehash;
%linehash=eval $_;
$bighash{'line'.$.}=\%linehash;
}
use Data::Dumper;
print Dumper(\%bighash);
__END__
%linehash=(key1=>'value1',key2=>'value2');
%linehash=(key3=>'value3',key4=>'value4');
%linehash=(key5=>'value5',key6=>'value6');
%linehash=(key7=>'value7',key8=>'value8',key9=>'value9');

Of course, with keys like those in %bighash, one could better use an array.


....

....
 
A

Anno Siegel

Aaron DeLoach said:
I create the hash from different data into a 'string' representation of a
hash and write it to the file. I extract them using the 'eval' function on
each line of the text file.
Aha.


I didn't think it did. However, when trying to create a 'main' hash of the
hashes (eval-ed strings) in the text file I need a 'key' name from the hash
name. That's where the problem lies (I think).

Yes, that's what I'm getting at a few lines below.

To store a value in a hash, you need a key to store it under. You
mentioned that yourself, but never said where the key is coming from.
That's whats created when I grep the file contents. Now i want to creata a
'main' hash containing each of the other hashes.

The first question you must answer for that is, where is the key
coming from.
I don't understand (forgive me).

Two essential features of your plan were unspecified: How to get the
(individual) hashes from each line, and how to get the key under which
to store it in the "super hash". So I just assumed there were routines
"get_hash" and "get_key" to extract them. Given those, the code
above should build the hash %super.

The "get_hash" routine can now be made more concrete:

sub get_hash { eval shift }

The "get_key" routine must still be filled in, you have not said where
the key is coming from.

Anno
 
C

ctcgag

Aaron DeLoach said:
I didn't think it did. However, when trying to create a 'main' hash of
the hashes (eval-ed strings) in the text file I need a 'key' name from
the hash name. That's where the problem lies (I think).

Yes, that is where the problem lies. But how can we help you with that
problem? If you don't know what you want to call these hashes, how are
we supposed to know?
That's whats created when I grep the file contents. Now i want to creata
a 'main' hash containing each of the other hashes.

If you don't know what you want to call each hash, what makes you think
you need to store them in a hash?

Xho
 
A

Aaron DeLoach

Anno Siegel said:
Yes, that's what I'm getting at a few lines below.


To store a value in a hash, you need a key to store it under. You
mentioned that yourself, but never said where the key is coming from.

I would like the key to be the hash name being extracted from the test file.
The first question you must answer for that is, where is the key
coming from.

I guess my question should have been phrased differently. It doesn't matter
where the hashes are coming from. The problem now verified was the fact that
a key name was needed.

What I wanted to achieve was the ability to create a 'main hash'
*containing* other hashes or HoH's - where the name of the hash being
incorporated into the 'main' hash was the hash name itself. For example:

File contains:
%hash1.....
%HoH...
%hash2...

ONE "Main" hash built from file:
%Main=(%hash1...%HoH...%hash2...);

The file containing the hashes is being built 'on the fly' by other
resources. I do not have prior knowledgs of how many, or the names thereof
the hashes inside.

With a function that would grep/eval/whatever the text file into a "main"
hash, I would be able to determine the names of the hashes incorporated by
looping through the outer keys.

The object is to (1) create the "main" hash; (2) destroy the original file;
(3) manipulate the "main" hash/sub-hashes; (4) rebuild the text file to
return to the original source.

I don't know if there is a better, or more efficient way of doing it?
 
A

Anno Siegel

Aaron DeLoach said:
I would like the key to be the hash name being extracted from the test file.

I think it's time you showed us a sample of the input lines (those that
are given to eval() to produce a hash).
I guess my question should have been phrased differently. It doesn't matter
where the hashes are coming from. The problem now verified was the fact that
a key name was needed.

Indeed. It's the key we're talking about. You need one, and in all
likelihood it will be extracted from the line that generates the key.
What I wanted to achieve was the ability to create a 'main hash'
*containing* other hashes or HoH's - where the name of the hash being
incorporated into the 'main' hash was the hash name itself. For example:

File contains:
%hash1.....
%HoH...
%hash2...

Are you saying the input file contains bits of code that assign hashes
to program variables? Again, show us a few examples.

If that is the case, the code in the input file is really part of the
source code and shouldn't be executed piece-wise through eval. You
should re-thing the design.
ONE "Main" hash built from file:
%Main=(%hash1...%HoH...%hash2...);

A hash isn't a sequence of other things, as "(%hash1...%HoH...%hash2...)"
would indicate. To store something in a hash you need a key, and to
retrieve something from a hash you also need a key. That you skip
the keys in your representation shows that you have no clear idea
of how a hash works.

As mentioned three or four replies back, you could build an array
of the resulting hashes:

@main = ( \ %hash1, \ %HoH, \ %hash2, ....);
The file containing the hashes is being built 'on the fly' by other
resources. I do not have prior knowledgs of how many, or the names thereof
the hashes inside.

That's the problem with variable names that are generated at run time.
You don't know what they are and cant access the data.

Instead of building code that assigns to a program variable, build
code that returns the hash without assigning it to a named variable.
Then you can eval it and assign the result to a known place.
With a function that would grep/eval/whatever the text file into a "main"

Now, "grep/eval/whatever" make strange bedfellows. Grep and eval aren't
alternatives to accomplish the same thing.
hash, I would be able to determine the names of the hashes incorporated by
looping through the outer keys.

You seem to hope the key names will magically appear once you have
the "main hash". It's the other way 'round. Before you can build
the main hash, you need a method to *assign* keys to each of the
partial hashes.

Anno
 
I

Ilmari Karonen

What I wanted to achieve was the ability to create a 'main hash'
*containing* other hashes or HoH's - where the name of the hash being
incorporated into the 'main' hash was the hash name itself. For example:

I presume your file actually looks something like this:

%hash1 = (key => 'value', key2 => 'value');
%hash2 = (key => 'value', subhash => {key => 'value', key2 => 'value'});
%hash3 = (key => 'value');

and so on. That is, the file is actually Perl code that creates the
hashes in the current package.

If so, you could always change to a different package and extract the
hashes from that package, something like this:

my $code = join "", <FILE>;

eval "package _temppkg; no strict 'vars'; $code";
die if $@;

my %mainhash;
foreach my $name (keys %_temppkg::) {
my $ref = *{$_temppkg::{$name}}{HASH} or next;
$mainhash{$name} = $ref;
}

(Ps. I do hope you really, *really* trust whatever it is that creates
the input file, since you're evaluating arbitrary Perl code from it.)
 
A

Aaron DeLoach

Ilmari Karonen said:
I presume your file actually looks something like this:

%hash1 = (key => 'value', key2 => 'value');
%hash2 = (key => 'value', subhash => {key => 'value', key2 => 'value'});
%hash3 = (key => 'value');

and so on. That is, the file is actually Perl code that creates the
hashes in the current package.

This is correct. The file is structured exactly as your sample above.
OurPerl code creates the data and places it within the file.
If so, you could always change to a different package and extract the
hashes from that package, something like this:

my $code = join "", <FILE>;

eval "package _temppkg; no strict 'vars'; $code";
die if $@;

my %mainhash;
foreach my $name (keys %_temppkg::) {
my $ref = *{$_temppkg::{$name}}{HASH} or next;
$mainhash{$name} = $ref;
}

Hmmm... Never thought of that. I 'll have to experiement with this process
as I'm not fully familliar with it.
(Ps. I do hope you really, *really* trust whatever it is that creates
the input file, since you're evaluating arbitrary Perl code from it.)

It's actually created by us, just not by the specific person updating the
information.
 

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

Members online

Forum statistics

Threads
473,767
Messages
2,569,573
Members
45,046
Latest member
Gavizuho

Latest Threads

Top