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

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

Dear Masters,

I'm trying to parse a text into a hash of array. Why can't my code below:
use Data::Dumper; my %hoa; while ( my $line = <DATA> ) { chomp $line; my $fname; if ( $line =~ /^[a-z]/ ) { $fname = $line; } elsif ($line =~ /^[0-9]+,/) { my $content = $line; push @{ $hoa{$fname} }, $content; } } # ----- end while ----- print Dumper \%hoa; #There are many datasets, here I just take 3 of them __DATA__ >data set dm01 >instances 0,-869,foofoofoofoofoofoofoofoo,28 0,-853,barbarbarbarbar,14 >data set yst02 >instances 0,-1566,quxquxquxqux,9 0,-1545,bembembem,9 0,-1394,birbirbirbir,9 >data set mus03 >instances 0,-1274,tingtingtingting,11 0,-1220,tongtongtong,11 0,-475,bubububu,11 0,-459,catcatcatcatcat,11
produce this data structure?
$HoA = { 'yst02'=> [ '0,-1566,quxquxquxqux,9', '0,-1545,bembembem,9', '0,-1394,birbirbirbir,9' ], 'dm01'=> [ '0,-869,foofoofoofoofoofoofoofoo,28', '0,-853,barbarbarbarbar,14' ], 'mus03'=> [ '0,-1274,tingtingtingting,11', '0,-1220,tongtongtong,11', '0,-475,bubububu,11', '0,-459,catcatcatcatcat,11', ], }


---
neversaint and everlastingly indebted.......

Replies are listed 'Best First'.
Re: How to Parse a Text into HoA
by japhy (Canon) on Nov 01, 2005 at 15:00 UTC
    The problem is that you're declaring $fname in every iteration of the loop, so it's always undef by the time you're using it as a hash key. Move the declaration of $fname OUTSIDE the while loop and you'll be ok.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: How to Parse a Text into HoA
by pg (Canon) on Nov 01, 2005 at 15:06 UTC

    You need to: 1)remember the $fname across loops, so define it outside; 2)also you need to my %hoa; 3) there is no need to define that $content.

    use Data::Dumper; use strict; use warnings; my %hoa; my $fname; while (my $line = <DATA>) { chomp $line; if ($line =~ /^[a-z]/ ) { $fname = $line; } elsif ($line =~ /^[0-9]+,/) { push @{$hoa{$fname}}, $line; } } print Dumper(\%hoa); __DATA__ >data set dm01 >instances 0,-869,foofoofoofoofoofoofoofoo,28 0,-853,barbarbarbarbar,14 >data set yst02 >instances 0,-1566,quxquxquxqux,9 0,-1545,bembembem,9 0,-1394,birbirbirbir,9 >data set mus03 >instances 0,-1274,tingtingtingting,11 0,-1220,tongtongtong,11 0,-475,bubububu,11 0,-459,catcatcatcatcat,11