http://qs321.pair.com?node_id=657139

DigitalKitty has asked for the wisdom of the Perl Monks concerning the following question:

Hi all.

I wrote a simple test file (test.txt):

Lateur Bart 97 Pierce Jerrad 96 Unknown planetscape 101 Miller Katie 86


Which I then read via the following perl program:

use warnings; use strict; use Data::Dumper; my %hash = (); my ($lname, $fname, $score); while( <> ) { ( $lname, $fname, $score ) = split; $hash{$lname}{$fname} = $score; } print Dumper(\%hash);


Since I am currently reading the 1st edition of 'Intermediate Perl' aka 'Perl Objects, References, and Modules', I am trying to understand how to read/interpret the output provided by Data::Dumper. If wanted to display the score each monk received or just their last name, how would I accomplish that? I tried...

print %{ $hash{$lname}{$fname}{$score} }\n";


...but noticed the following complaints:

C:\Perl\bin>perl test16.pl test.txt Global symbol "$lname" requires explicit package name at test16.pl lin +e 12. Global symbol "$fname" requires explicit package name at test16.pl lin +e 12. Global symbol "$score" requires explicit package name at test16.pl lin +e 12. Execution of test16.pl aborted due to compilation errors.


Any constructive advice would be most appreciated.

Thanks,
~Katie

Update: Solved the 'explicit package name issues' by declaring the lexical variables outside of the while loop.

Replies are listed 'Best First'.
Re: Deciphering the output from Data::Dumper
by FunkyMonk (Chancellor) on Dec 14, 2007 at 23:32 UTC
    You've confused their first and last names. The data is <lname fname score> but you assign those to $fname, $lname, $score
    my %hash = (); while( <DATA> ) { my( $lname, $fname, $score ) = split; $hash{$lname}{$fname} = $score; } #just last names print join "\n", keys %hash; print "\n---\n"; #names and scores: for my $lname ( keys %hash ) { for my $fname ( keys %{ $hash{$lname} } ) { printf "$lname, $fname: $hash{$lname}{$fname}\n" } } __DATA__ Lateur Bart 97 Pierce Jerrad 96 Unknown planetscape 101 Miller Katie 86

    Output:

    Pierce Lateur Miller Unknown --- Pierce, Jerrad: 96 Lateur, Bart: 97 Miller, Katie: 86 Unknown, planetscape: 101

      Methinks FunkyMonk hit this on the head....
      and adding Data::Dumper to the mix above,
      use Data::Dumper; print Dumper %hash;
      gives you reasonable (readable) output:
      $VAR1 = 'Pierce'; $VAR2 = { 'Jerrad' => '96' }; $VAR3 = 'Lateur'; $VAR4 = { 'Bart' => '97' }; $VAR5 = 'Miller'; $VAR6 = { 'Katie' => '86' }; $VAR7 = 'Unknown'; $VAR8 = { 'planetscape' => '101' };
Re: Deciphering the output from Data::Dumper
by Limbic~Region (Chancellor) on Dec 15, 2007 at 01:20 UTC
    DigitalKitty,
    One of the issues you have is that you have not given names to your keys. Instead, you have used a value as a key. This is why the output of Data::Dumper is confusing. Consider this alternative:
    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my %data; while (<DATA>) { chomp; my ($ln, $fn, $score) = split ' '; $data{$ln} = {fn => $fn, score => $score}; } print Dumper(\%data); # Show just last names print "$_\n" for sort keys %data; # Show name and score for my $ln (sort keys %data) { my ($fn, $score) = @{$data{$ln}}{qw/fn score/}; print "$ln\t$fn\t$score\n"; } __DATA__ Lateur Bart 97 Pierce Jerrad 96 Unknown planetscape 101 Miller Katie 86

    Cheers - L~R

Re: Deciphering the output from Data::Dumper
by pascaldee (Acolyte) on Dec 16, 2007 at 02:44 UTC
    Btw, consider replacing Data::Dumper with Data::Dump. It's about time already.