need help with hash - been too long working in Perl
am 27.10.2007 21:57:14 von JerryP
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_ = ;
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
am 27.10.2007 23:45:17 von Ron Bergin
My system seamed to hang while posting, so this may end up as a double
post.
On Oct 27, 12:57 pm, JerryP 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_ = ;
> 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() {
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
am 28.10.2007 03:47:52 von krahnj
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_ = ;
> 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 ( ) {
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