need help with hash - been too long working in Perl

J

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_ = <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
 
R

Ron Bergin

My system seamed to hang while posting, so this may end up as a double
post.

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
 
J

John W. Krahn

JerryP said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top