in reply to Hash of hashes syntax

O.k. Here's your code, quick-fixed:
my %hash_of_hashes; while (<UNITFILES>) { my @unitfiles_field = split /,/; # this is just an autogen number my $record = $unitfiles_field[0]; my %unitfiles_hash = ( lastname => $unitfiles_field[1], firstname => $unitfiles_field[2], DOB => $unitfiles_field[7], funding => $unitfiles_field[18], URNo => $unitfiles_field[15], Photo_permission => $unitfiles_field[14], ); # add this hash to the hash-of-hashes: $hash_of_hashes{$record_no} = \%unitfiles_hash; }
I'd probably make it somewhat cleaner, like so:
my %hash_of_hashes; while (<UNITFILES>) { my @f = split /,/; $hash_of_hashes{$f[0]} = { lastname => $f[1], firstname => $f[2], DOB => $f[7], funding => $f[18], URNo => $f[15], Photo_permission => $f[14], }; }
Or I might even consider the following. (TIMTOWTDI!)
my %hash_of_hashes; while (<UNITFILES>) { my %h; (my $rn, @h{ qw(lastname firstname DOB funding URNo Photo_permission) }) = (split /,/)[0,1,2,7,18,15,14]; $hash_of_hashes{$rn} = \%h; }

jdporter
The 6th Rule of Perl Club is -- There is no Rule #6.

Replies are listed 'Best First'.
Re: Re: Hash of hashes syntax
by bwana147 (Pilgrim) on Mar 19, 2003 at 08:41 UTC

    I'm afraid your last solution, as concise as it might be, simply does not work. \%h always refers to the same hash. You may well change its content at each loop, you're always modifying the same hash, and all members of %hash_of_hashes refer to it.

    You really must create a new hash at each loop. This will do it:

    $hash_of_hashes{$rn} = { %h };
    (the hash keys and values are flattened into a list, which in turn is used to create an anonymous hash).

    --bwana147

      I'm afraid your last solution, as concise as it might be, simply does not work. \%h always refers to the same hash

      Not true.

      In this case, it would refer to a different hash. This is because the variable my %h is lexically scoped, and thus it is recreated each time through the loop, and so \%h will point to a different hash each time through the loop. To illustrate what I mean here is some code:

      The differences are subtle, but jdporter's code works.

      -enlil

      Good eye, but this actually isn't a problem in this case. Because of the my %h inside of the loop, %h is a different (and new) lexical through each iteration -- thus there is no problem just sticking a reference to it into the hash or array. The problem comes from code like this (nearly directly copied from perldsc):

      my %hash; for $i (1..10) { %hash = somefunc($i); $hash_of_hashes{$rn} = \%hash; # WRONG! }

      Note where the "my" is. See perldsc or perlreftut or perllol for more.

      perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'