![]() |
need help with hash - been too long working in Perl
Hi!
This is simple? But it has been a while that I have programmed in Perl. What I am wanting to do is build a hash from a text file: text: 79706-0000 2229.17 79706-0000 2523.25 79701-0000 53904.48 79701-0000 78957.81 79701-0000 378043.04 79701-0000 1255172.34 79702-0000 7367.23 79702-0000 20742.95 79702-0000 67331.82 79702-0000 137629.57 79703-0000 1444.18 79701-0000 57565.48 79703-0000 2415.00 79703-0000 2787.97 79703-0000 4780.55 79703-0000 5061.21 79703-5011 1125.80 79704-0000 2382.31 79705-0000 4612.65 79706-0000 1416.50 79703-0000 64014.50 With script: use strict; local( *FI, *FO ); my @text = (); my @zip = (); my %ref; open ( FI, "msj_sare.lst" ) or die "Couldn't open c:\\vf\ \sj_sare.lst"; my @text_ = <FI>; close FI; s/\n// for( @text = @text_ ); foreach ( @text ) { /(\d+)\-(\d+)(\s+)(-?(?:\d+(?:\.\d*)?|\.\d+))/; push( @zip, $1 ); push( @{ $ref{ $1 }{ $2 }},$_ ); } # then sort with open ( FO, "+>msj_sare.jwp" ) or die "Couldn't open c:\\vf\ \sj_sare.jwp"; foreach my $family ( sort keys %ref ) { # for my $role ( sort { $ref{$b} <=> $ref{$a} } keys % { $ref{$family} } ) { print " $family*$ref{ $family }*\n"; for my $role ( sort keys %{ $ref{$family} } ) { print(join(', ',sort keys ${ $ref{$family} }),"\n"); # print "$ref{$family}{$role}[0]\n"; print FO "$ref{$family}{$role}[0]\n"; } print FO "\n"; } I am wanting to print out the data in the following format: 79701-0000 1255172.34 79701-0000 378043.04 79701-0000 78957.81 79701-0000 57565.48 79701-0000 53904.48 79702-0000 137629.57 79702-0000 67331.82 79702-0000 20742.95 79702-0000 7367.23 79703-0000 64014.50 79703-0000 5061.21 79703-0000 2787.97 79703-0000 2415.00 79703-0000 4780.55 79703-0000 1444.18 79703-5011 1125.80 79704-0000 2382.31 79705-0000 4612.65 79706-0000 2523.25 79706-0000 2229.17 79706-0000 1416.50 Thanks, Jerry |
Re: need help with hash - been too long working in Perl
My system seamed to hang while posting, so this may end up as a double
post. On Oct 27, 12:57 pm, JerryP <gjwp...@gmail.com> wrote: > Hi! > > This is simple? But it has been a while that I have programmed in > Perl. What I am wanting to do is build a hash from a text file: > > text: > > 79706-0000 2229.17 > 79706-0000 2523.25 > 79701-0000 53904.48 > 79701-0000 78957.81 > 79701-0000 378043.04 > 79701-0000 1255172.34 > 79702-0000 7367.23 > 79702-0000 20742.95 > 79702-0000 67331.82 > 79702-0000 137629.57 > 79703-0000 1444.18 > 79701-0000 57565.48 > 79703-0000 2415.00 > 79703-0000 2787.97 > 79703-0000 4780.55 > 79703-0000 5061.21 > 79703-5011 1125.80 > 79704-0000 2382.31 > 79705-0000 4612.65 > 79706-0000 1416.50 > 79703-0000 64014.50 > > With script: > > use strict; > local( *FI, *FO ); Why are you using local on the file handles, which appear to have file scope? > my @text = (); > my @zip = (); It doesn't hurt, but there is no need to initialize the arrays with an empty list. > my %ref; > > open ( FI, "msj_sare.lst" ) or die "Couldn't open c:\\vf\ > \sj_sare.lst"; You should be using the 3 arg form of open and you should probably include $! in the die statement to output the reason why it failed. > my @text_ = <FI>; > close FI; It's almost never a good idea to slurp the entire file into an array. Instead, you should loop through it. > > s/\n// for( @text = @text_ ); Use chomp while looping through the file to remove \n. > > foreach ( @text ) { > /(\d+)\-(\d+)(\s+)(-?(?:\d+(?:\.\d*)?|\.\d+))/; > push( @zip, $1 ); > push( @{ $ref{ $1 }{ $2 }},$_ ); > } This is a personal preference, but I'd simplify the regex and use 1 push instead of 2. > > # then sort with > > open ( FO, "+>msj_sare.jwp" ) or die "Couldn't open c:\\vf\ > \sj_sare.jwp"; > > foreach my $family ( sort keys %ref ) { > > # for my $role ( sort { $ref{$b} <=> $ref{$a} } keys % > { $ref{$family} } ) { > print " $family*$ref{ $family }*\n"; > > for my $role ( sort keys %{ $ref{$family} } ) { > print(join(', ',sort keys ${ $ref{$family} }),"\n"); > # print "$ref{$family}{$role}[0]\n"; > print FO "$ref{$family}{$role}[0]\n"; > } > print FO "\n"; > } > > I am wanting to print out the data in the following format: > > 79701-0000 1255172.34 > 79701-0000 378043.04 > 79701-0000 78957.81 > 79701-0000 57565.48 > 79701-0000 53904.48 > > 79702-0000 137629.57 > 79702-0000 67331.82 > 79702-0000 20742.95 > 79702-0000 7367.23 > > 79703-0000 64014.50 > 79703-0000 5061.21 > 79703-0000 2787.97 > 79703-0000 2415.00 > 79703-0000 4780.55 > 79703-0000 1444.18 > 79703-5011 1125.80 > > 79704-0000 2382.31 > > 79705-0000 4612.65 > > 79706-0000 2523.25 > 79706-0000 2229.17 > 79706-0000 1416.50 > > Thanks, > > Jerry use strict; use warnings; my %data; while(<DATA>) { my ($key) = /^(\d+)/; my ($subkey, $value) = split /\s+/; push @{$data{$key}{$subkey}}, $value; } foreach my $key ( sort keys %data ) { foreach my $subkey ( sort keys %{$data{$key}} ) { foreach my $value ( sort {$b <=> $a} @{$data{$key}{$subkey}} ) { printf "%s %12.2f\n", $subkey, $value; } } print "\n"; } __DATA__ 79706-0000 2229.17 79706-0000 2523.25 79701-0000 53904.48 79701-0000 78957.81 79701-0000 378043.04 79701-0000 1255172.34 79702-0000 7367.23 79702-0000 20742.95 79702-0000 67331.82 79702-0000 137629.57 79703-0000 1444.18 79701-0000 57565.48 79703-0000 2415.00 79703-0000 2787.97 79703-0000 4780.55 79703-0000 5061.21 79703-5011 1125.80 79704-0000 2382.31 79705-0000 4612.65 79706-0000 1416.50 79703-0000 64014.50 |
Re: need help with hash - been too long working in Perl
JerryP wrote:
> > This is simple? But it has been a while that I have programmed in > Perl. What I am wanting to do is build a hash from a text file: > > text: > > 79706-0000 2229.17 > 79706-0000 2523.25 > 79701-0000 53904.48 > 79701-0000 78957.81 > 79701-0000 378043.04 > 79701-0000 1255172.34 > 79702-0000 7367.23 > 79702-0000 20742.95 > 79702-0000 67331.82 > 79702-0000 137629.57 > 79703-0000 1444.18 > 79701-0000 57565.48 > 79703-0000 2415.00 > 79703-0000 2787.97 > 79703-0000 4780.55 > 79703-0000 5061.21 > 79703-5011 1125.80 > 79704-0000 2382.31 > 79705-0000 4612.65 > 79706-0000 1416.50 > 79703-0000 64014.50 > > With script: > > use strict; > local( *FI, *FO ); You really don't need to local()ize those typeglobs. > my @text = (); > my @zip = (); > my %ref; > > open ( FI, "msj_sare.lst" ) or die "Couldn't open c:\\vf\ > \sj_sare.lst"; You are trying to open "msj_sare.lst" but your error message says you tried to open "c:\\vf\\sj_sare.lst"? You should include the $! (or $^E) variable in the error message so you know *why* the open failed. > my @text_ = <FI>; > close FI; > > s/\n// for( @text = @text_ ); > > foreach ( @text ) { > /(\d+)\-(\d+)(\s+)(-?(?:\d+(?:\.\d*)?|\.\d+))/; You shouldn't use the numeric variables unless the match was successful or they will contain values from the last successful match. You are capturing $3 and $4 but you are not using their contents? > push( @zip, $1 ); > push( @{ $ref{ $1 }{ $2 }},$_ ); > } > > # then sort with > > open ( FO, "+>msj_sare.jwp" ) or die "Couldn't open c:\\vf\ > \sj_sare.jwp"; You are trying to open "msj_sare.jwp" but your error message says you tried to open "c:\\vf\\sj_sare.jwp"? You are opening the file for both reading and writing but you are not reading from the file? You should include the $! (or $^E) variable in the error message so you know *why* the open failed. > foreach my $family ( sort keys %ref ) { > > # for my $role ( sort { $ref{$b} <=> $ref{$a} } keys % > { $ref{$family} } ) { > print " $family*$ref{ $family }*\n"; > > for my $role ( sort keys %{ $ref{$family} } ) { > print(join(', ',sort keys ${ $ref{$family} }),"\n"); > # print "$ref{$family}{$role}[0]\n"; > print FO "$ref{$family}{$role}[0]\n"; > } > print FO "\n"; > } > > I am wanting to print out the data in the following format: > > 79701-0000 1255172.34 > 79701-0000 378043.04 > 79701-0000 78957.81 > 79701-0000 57565.48 > 79701-0000 53904.48 > > 79702-0000 137629.57 > 79702-0000 67331.82 > 79702-0000 20742.95 > 79702-0000 7367.23 > > 79703-0000 64014.50 > 79703-0000 5061.21 > 79703-0000 2787.97 > 79703-0000 2415.00 > 79703-0000 4780.55 > 79703-0000 1444.18 > 79703-5011 1125.80 > > 79704-0000 2382.31 > > 79705-0000 4612.65 > > 79706-0000 2523.25 > 79706-0000 2229.17 > 79706-0000 1416.50 It *looks* like you might want the second column in sorted order but the line: 79703-0000 4780.55 is not in sorted order? Perhaps you want something like this: use warnings; use strict; open FI, '<', 'msj_sare.lst' or die "Couldn't open 'msj_sare.lst' $!"; open FO, '>', 'msj_sare.jwp' or die "Couldn't open 'msj_sare.jwp' $!"; my %ref; while ( <FI> ) { if ( /(\d+)-(\d+)\s+-?(?:\d+\.\d*|\.?\d+)/ ) { push @{ $ref{ $1 }{ $2 } }, $_; } } for my $family ( sort { $a <=> $b } keys %ref ) { for my $role ( sort { $a <=> $b } keys %{ $ref{ $family } } ) { print FO @{ $ref{ $family }{ $role } }, "\n"; } } __END__ John -- use Perl; program fulfillment |
| All times are GMT. The time now is 11:01 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.