Search code examples
perlloopshashdata-dumperhashref

Perl - Hash reference structure of variable depth


I have a question I am hoping someone could help with.

I have a tab-delimited text file called FILE.txt:

(note two of the ages are missing):

BOY    Fred      Smith     56
BOY    David     Jones     18
GIRL   Anne      Roberts   
BOY    Fred      Andrews
GIRL   Hannah    Williams  27

I want to read the text file into a hash/hash reference data structure (something like what is shown below):

open my $f, '<', 'FILE.txt';
my $details;
while (<$f>) {
    chomp;
    my ( $gender, $firstName, $middleName, $lastName, $age) = split("\t");
    $details->{$gender}->{$firstName}->{$lastName} = "$age";
}
  • Is this the correct way to make the structure because sometimes there may not be an age in the text file?

With this hash/hash reference structure I then want to print the details of the people, but because some of the people do not have ages. This causes problems with empty values in the hash and unitialised values and so on.

Here is the data it produces:

{
  BOY  => { David => { Jones => 18 }, Fred => { Andrews => "", Smith => 56 } },
  GIRL => { Anne => { Roberts => "" }, Hannah => { Williams => 27 } },
}
  • How do you accomodate instances where the person does not have an age specified in FILE.txt?
  • How do you make this data structure properly if it is of variable depth and then access it properly?

I know how to make and access the different parts of a hash/hash reference if it is of a fixed/known depth, but what is the best way to do this when the data structure could have different depths?

Your help is much appreciated, thanks


Solution

  • There should not be problem in storing blank values of age!

    It is a value, the key has to be unique in a hash data structure.

    The way you have done it is right!

    Else, it would be better if you make it blank.

    i.e.:

    my ( $gender, $firstName, $middleName, $lastName, $age) = split("\t") ;
    if($age =~ /\d+/) {
       $details->{$gender}->{$firstName}->{$lastName} = "$age"; 
    } else {
       $details->{$gender}->{$firstName}->{$lastName} = ""; 
    }