Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Perl Misc (http://www.velocityreviews.com/forums/f67-perl-misc.html)
-   -   need help with hash - been too long working in Perl (http://www.velocityreviews.com/forums/t905111-need-help-with-hash-been-too-long-working-in-perl.html)

JerryP 10-27-2007 07:57 PM

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


Ron Bergin 10-27-2007 09:45 PM

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


John W. Krahn 10-28-2007 02:47 AM

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 10:15 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.