Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Help with creating and passing of an array...

by basicdez (Pilgrim)
on Nov 14, 2001 at 03:48 UTC ( [id://125174]=perlquestion: print w/replies, xml ) Need Help??

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

I am having problems with creating this two dimensional array and need to create it for several different lines of this data file. If any of you could please look at this code and help me out, I would be a smiling monk...
#!/usr/bin/perl-Tw use strict; use Text::ParseWords; my $fname = "CommaSample.dat"; my $pretty = 1; my $ADR_Ind = 0; my $PER_Ind = 0; my $EMP_Ind = 0; my @PER_Data; my @major_PER_Data; BARE: { my ($toggle, @data) = (''); open FH, "< $fname" or die "Cannot open datfile: ", $!; while (<FH>) { if (/"PER"/) { $toggle = 1, next if /^"PER"\s*$/; } elsif (/^"EMP"\s*$/) { $toggle = 2, next if /^"EMP"\s*$/; } elsif (/^"ADR"\s*$/) { $toggle = 3, next if /^"ADR"\s*$/; } last if /^"EOS"\s*$/; die "Unknown or missing record tag: Got $_ on line $., datafil +e $fname.$/" if $toggle eq ''; chomp; @data = &quotewords('\s+', 0, $_); if ($toggle == 1) { my $Per_Entity = $data[0]; my $Name = $data[1]; my $Color = $data[2]; my $Date = $data[3]; $toggle = 0; @PER_Data = ($Per_Entity, $Name, $Color, $Date); push @major_PER_Data, \@PER_Data; } $toggle = ''; print $/ if $pretty; } print $/; } print "Personal Data...\n"; foreach my $item (@major_PER_Data) { foreach my $subitem (@{$item}) { print $subitem,"\n"; } }
This is the data file that I am using...
"PER" "A1" "Denise Johnson" "red,orange,yellow,green,blue,purple" 09/25/2001 "PER" "A2" "Suzanne Summers" "blue,green,yellow,blue-green" 07/24/1995 "EMP" "A1" "X & Y Bank" "Teller" 05/17/1994 "Brian's Point" "WI" 54997 24000 +.00 "EMP" "A2" "Acme Corp" "Computer Programmer" 07/24/1997 "Maxwell" "WI" 53224 + 45000.00 "ADR" "A1" "264 E Dekora St NO 1" "Saukville" "WI" 53080 3 6 "ADR" "A2" "111 E Dogwood St NO 1" "Pittsville" "WA" 46758 4 8 "EOS"
If you run this program you will see that what is happening is it is creating a two dimensional array with double values of A2 PER info being pushed into the array. Ideally I would like A1 PER info and then A2 PER info. If you have any advice that would help, please help me out. peace, LOVE and ((code)) basicdez

Replies are listed 'Best First'.
Re: Help with creating and passing of an array...
by IraTarball (Monk) on Nov 14, 2001 at 04:44 UTC
    I think I found your problem

    The array @PER_Data; is outside of the while loop. This means that it is not going to be destroyed until the program ends. So the line

    push @major_PER_Data, \@PER_Data;
    pushes the same reference over and over again. Then the next time through the modification overwrites the data you thought you saved.

    you can fix this by either moving the declaration of @PER_DATA inside the while loop or by changing the above line to

    push @major_PER_Data, [@PER_Data];

    Hope this helps,
    Ira,

    "So... What do all these little arrows mean?"
    ~unknown

      Thank you so much for you wonderful help. That is exactly what I was looking for. peace, LOVE and ((code)) basicdez
Re: Help with creating and passing of an array...
by Zaxo (Archbishop) on Nov 14, 2001 at 11:23 UTC

    I think I recognise some of this ;-) First, your if(){}elsif(){}else(){} is redundant. The 'assignment,next if match' construction does exactly the same thing.

    Second, lets rethink the data structure. Using arrays means that you have to hard code labels, keep track of positions, generally keep a lot of state in your program. I think this screams for a hashes.

    I'll take the code in order:

    #!/usr/bin/perl-Tw use strict; use Text::ParseWords; my $fname = "CommaSample.dat"; my $pretty = 1; my %major_PER_Data = (); my %major_EMP_Data = (); my %major_ADR_Data = (); { my ($toggle, @data) = (0); open FH, "< $fname" or die "Cannot open datfile: ", $!; while (<FH>) { chomp; @data = &quotewords('\s+', 0, $_); $toggle = 1, next if $data[0]=~/PER/; $toggle = 2, next if $data[0]=~/EMP/; $toggle = 3, next if $data[0]=~/ADR/; last if $data[0]=~/EOS/; die "Unknown or missing record tag: ", "Got $_ on line $., ", "datafile $fname.$/" if !$toggle; chomp; @data = &quotewords('\s+', 0, $_); if ($toggle == 1) { $major_PER_Data{data[0]} = { Name => [$data[1]], Color => [split /\s*,\s*/, $data[2]], Date => [$data[3]]}; } elsif ($toggle == 2) { $major_EMP_Data{data[0]} = { Company => [$data[1]], Position => [$data[2]], Date => [$data[3]], City => [$data[4]], State => [$data[5]], SecretCode => [$data[6]], RoundNumber => [$data[7]], Bugeyes => [$data[8]], } elsif ($toggle == 3) { $major_ADR_Data{data[0]} = { Street => [$data[1]], City => [$data[2]], State => [$data[3]], Zip => [$data[4]], Mileage => [$data[5]], MoreCode => [$data[6]]}; } $toggle = 0; } } print "Personal Data...$/"; for my $entity ( sort keys %major_PER_Data) { # only getting these from one hash, using for all three print $entity,$/; for my $item (qw(Name Color Date)) { print map {"$item: $_$/"} @{$major_PER_Data{$entity}->{$item} +}; } # ... and so on for %major_others }
    I kept your organization as much as possible, but I would be better to key first on "Entity" within a single hash referencing a hash with keys 'PER', 'ADR', and 'EMP'. I'm assuming Entity is a unique identifier.

    There are lots of ways to improve this. I'd try factoring out the data parsing to subroutines, keeping arrays of each line's field names, and making use of slices.

    After Compline,
    Zaxo

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://125174]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2024-03-29 00:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found