Generation of A HASH OF HASHES: # Reading From File

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 11

Generation of a HASH OF HASHES

# reading from file

# flintstones: lead=fred pal=barney wife=wilma pet=dino

while ( <> ) {

next unless s/^(.*?):\s*//;

$who = $1;

for $field ( split ) {

($key, $value) = split /=/, $field;

$HoH{$who}{$key} = $value;

# reading from file; more temps

while ( <> ) {

next unless s/^(.*?):\s*//;

$who = $1;

$rec = {};

$HoH{$who} = $rec;

for $field ( split ) {

($key, $value) = split /=/, $field;

$rec->{$key} = $value;
}

# calling a function that returns a key,value hash

for $group ( "simpsons", "jetsons", "flintstones" ) {

$HoH{$group} = { get_family($group) };

# likewise, but using temps

for $group ( "simpsons", "jetsons", "flintstones" ) {

%members = get_family($group);

$HoH{$group} = { %members };

# append new members to an existing family

%new_folks = (

wife => "wilma",

pet => "dino",

);

for $what (keys %new_folks) {

$HoH{flintstones}{$what} = $new_folks{$what};
}

Access and Printing of a HASH OF HASHES

# one element

$HoH{flintstones}{wife} = "wilma";

# another element

$HoH{simpsons}{lead} =~ s/(\w)/\u$1/;

# print the whole thing

foreach $family ( keys %HoH ) {

print "$family: { ";

for $role ( keys $HoH{$family}->%* ) {

print "$role=$HoH{$family}{$role} ";

print "}\n";

# print the whole thing somewhat sorted

foreach $family ( sort keys %HoH ) {

print "$family: { ";

for $role ( sort keys $HoH{$family}->%* ) {

print "$role=$HoH{$family}{$role} ";


}

print "}\n";

# print the whole thing sorted by number of members

foreach $family ( sort { $HoH{$b}->%* <=> $HoH{$a}->%* } keys %HoH ) {

print "$family: { ";

for $role ( sort keys $HoH{$family}->%* ) {

print "$role=$HoH{$family}{$role} ";

print "}\n";

# establish a sort order (rank) for each role

$i = 0;

for ( qw(lead wife son daughter pal pet) ) { $rank{$_} = ++$i }

# now print the whole thing sorted by number of members

foreach $family ( sort { $HoH{$b}->%* <=> $HoH{$a}->%* } keys %HoH ) {

print "$family: { ";

# and print these according to rank order


for $role ( sort { $rank{$a} <=> $rank{$b} }

keys $HoH{$family}->%* )

print "$role=$HoH{$family}{$role} ";

print "}\n";

MORE ELABORATE RECORDS


Declaration of MORE ELABORATE RECORDS
Here's a sample showing how to create and use a record whose fields are of many
different sorts:

$rec = {

TEXT => $string,

SEQUENCE => [ @old_values ],

LOOKUP => { %some_table },

THATCODE => \&some_function,

THISCODE => sub { $_[0] ** $_[1] },

HANDLE => \*STDOUT,

};

print $rec->{TEXT};
print $rec->{SEQUENCE}[0];

$last = pop $rec->{SEQUENCE}->@*;

print $rec->{LOOKUP}{"key"};

($first_k, $first_v) = each $rec->{LOOKUP}->%*;

$answer = $rec->{THATCODE}->($arg);

$answer = $rec->{THISCODE}->($arg1, $arg2);

# careful of extra block braces on fh ref

print { $rec->{HANDLE} } "a string\n";

use FileHandle;

$rec->{HANDLE}->autoflush(1);

$rec->{HANDLE}->print(" a string\n");

Declaration of a HASH OF COMPLEX RECORDS

%TV = (

flintstones => {

series => "flintstones",

nights => [ qw(monday thursday friday) ],

members => [

{ name => "fred", role => "lead", age => 36, },


{ name => "wilma", role => "wife", age => 31, },

{ name => "pebbles", role => "kid", age => 4, },

],

},

jetsons => {

series => "jetsons",

nights => [ qw(wednesday saturday) ],

members => [

{ name => "george", role => "lead", age => 41, },

{ name => "jane", role => "wife", age => 39, },

{ name => "elroy", role => "kid", age => 9, },

],

},

simpsons => {

series => "simpsons",

nights => [ qw(monday) ],

members => [

{ name => "homer", role => "lead", age => 34, },

{ name => "marge", role => "wife", age => 37, },

{ name => "bart", role => "kid", age => 11, },


],

},

);

Generation of a HASH OF COMPLEX RECORDS

# reading from file

# this is most easily done by having the file itself be

# in the raw data format as shown above. perl is happy

# to parse complex data structures if declared as data, so

# sometimes it's easiest to do that

# here's a piece by piece build up

$rec = {};

$rec->{series} = "flintstones";

$rec->{nights} = [ find_days() ];

@members = ();

# assume this file in field=value syntax

while (<>) {

%fields = split /[\s=]+/;

push @members, { %fields };

$rec->{members} = [ @members ];
# now remember the whole thing

$TV{ $rec->{series} } = $rec;

###########################################################

# now, you might want to make interesting extra fields that

# include pointers back into the same data structure so if

# change one piece, it changes everywhere, like for example

# if you wanted a {kids} field that was a reference

# to an array of the kids' records without having duplicate

# records and thus update problems.

###########################################################

foreach $family (keys %TV) {

$rec = $TV{$family}; # temp pointer

@kids = ();

for $person ( $rec->{members}->@* ) {

if ($person->{role} =~ /kid|son|daughter/) {

push @kids, $person;

# REMEMBER: $rec and $TV{$family} point to same data!!

$rec->{kids} = [ @kids ];
}

# you copied the array, but the array itself contains pointers

# to uncopied objects. this means that if you make bart get

# older via

$TV{simpsons}{kids}[0]{age}++;

# then this would also change in

print $TV{simpsons}{members}[2]{age};

# because $TV{simpsons}{kids}[0] and $TV{simpsons}{members}[2]

# both point to the same underlying anonymous hash table

# print the whole thing

foreach $family ( keys %TV ) {

print "the $family";

print " is on during $TV{$family}{nights}->@*\n";

print "its members are:\n";

for $who ( $TV{$family}{members}->@* ) {

print " $who->{name} ($who->{role}), age $who->{age}\n";

}
print "it turns out that $TV{$family}{lead} has ";

print scalar ( $TV{$family}{kids}->@* ), " kids named ";

print join (", ", map { $_->{name} } $TV{$family}{kids}->@* );

print "\n";

Database Ties
You cannot easily tie a multilevel data structure (such as a hash of hashes) to a dbm file.
The first problem is that all but GDBM and Berkeley DB have size limitations, but beyond
that, you also have problems with how references are to be represented on disk. One
experimental module that does partially attempt to address this need is the MLDBM
module. Check your nearest CPAN site as described in perlmodlib for source code to
MLDBM.

You might also like