Advanced Data Structures

#!/usr/bin/perl -w
###################  List of Hash as Array of Records  ######################
 
###############  What's wrong with this?
##  %personnel = (
##        "123456" => ["James Thomas", 46, 54344],
##        "789098" => ["Mister Ed", 24, 40000],
##        "345678" => ["Buck Naked", 40, 99000]);
##  
###############  Answer:  Fields are unnamed!
###############  Solution:  List of hashes below.
###############  Note:  { } is a reference to an anonymous hash.

@people = (   ##  People is a list of hashes!
 { "ID" => "123456", "NAME" => "James Thomas", "AGE" => 46, "SALARY" => 54344},
 { "ID" => "789098", "NAME" => "Mister Ed", "AGE" => 24, "SALARY" => 40000},
 { "ID" => "345678", "NAME" => "Buck Naked", "AGE" => 40, "SALARY" => 99000});

print $people[1]->{NAME}, "\n";
undef @people;

#######  The comments below show the format of file "data".
#######  123456 James Thomas 46 54344
#######  789098 Mister Ed 24 40000
#######  345678 Buck Naked 40 99000

open(F,"data") or die "Cannot read data file.\n";

while(<F>)
{
      @fields = split;
      $name = $fields[1]." ".$fields[2];
      splice(@fields, 1, 2, $name);
      @person{ID,NAME,AGE,SALARY} = @fields;  ##  A hash slice!!!
      push(@people, {%person});   ##  Passing \%person will not work!!  Why?
}

foreach $personRef (@people)
{
      %temp = %$personRef;
      print "@temp{ID,NAME,AGE,SALARY}\n";
}

change_age_to_50(\@people);

foreach $personRef (@people)
{
      %temp = %$personRef;   ##  Trick to use hash slice in next line!
      print "@temp{ID,NAME,AGE,SALARY}\n";
}
 

sub change_age_to_50
{
      my ($peopleRef) = @_;
      my $personRef;

      foreach $personRef (@$peopleRef) { $personRef->{AGE} = 50 }
}     
#############################  Program Output  ############################

Mister Ed     ##  $people[1]->{NAME}

123456 James Thomas 46 54344   ##  Hash dump.
789098 Mister Ed 24 40000
345678 Buck Naked 40 99000

123456 James Thomas 50 54344    ##  Ages all fifty after sub is called.
789098 Mister Ed 50 40000
345678 Buck Naked 50 99000
##########################################################################

#!/usr/bin/perl -w

##############  Hash of Hash and Other Complex Record Types  ###############

%people = ( "Fred Jones" => {"AGE" => 45, "SALARY" => 90000},
            "Joe Smith"  => {"AGE" => 32, "SALARY" => 36400},
            "Mary Arne"  => {"AGE" => 29, "SALARY" => 66122},
            "Ted Carney" => {"AGE" => 56, "SALARY" => 100000} );

foreach $key (keys %people)
{
     print "$key $people{$key}->{AGE} $people{$key}->{SALARY}\n";
     %temp = %{$people{$key}};
     print "$key @temp{AGE,SALARY}\n";  ##  Trick to use hash slice.
} 

##############  Heterogenous Hashes -- Not All Elements Must be the Same Type!!

%weird = ("SUBNAME" => [\&subA, \&subB, \&subC],
          "SCALAR"  => 5,
          "PARTSPEC" => {"NAME" => "bolt", "NUMBER" => 12345, "PRICE" => 1.45});

sub subA { print "I am subA!\n" }
sub subB { print "I am subB!\n" }
sub subC { print "I am subC!\n" }

&{$weird{SUBNAME}->[1]};  ##  Sneaky execution of subB.  & is required here!!
print "$weird{PARTSPEC}->{PRICE}\n";  ##  Should be 1.45
#############################  Program Output  #############################

Fred Jones 45 90000
Fred Jones 45 90000
Joe Smith 32 36400
Joe Smith 32 36400
Ted Carney 56 100000
Ted Carney 56 100000
Mary Arne 29 66122
Mary Arne 29 66122

I am subB!

1.45