Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using two arrays in an Array 1

Status
Not open for further replies.

hello99hello

Programmer
Jul 29, 2004
50
0
0
CA
Hello All,

I have a file with the following records:

Jasmin,Long ,23$45 ,1234A, MATLV, 0, 3
David ,Malow, 3328$,7765B, CRTLV, 2, 4
.
.
.
.
Susan ,Hagen, $8699 ,87564, VACLV, 0, 5

My aim is to have output file that has the following:
#The whole records in the file have to be put in an array.
#Also, columns 3,4, 5 and 6 has to be put in seperate arrays because the are too many #records. I am hoping to write foreach loop and for loop for the soltution.

Here is my effort:
@array_file = <INPUT> ;
foreach $array_record (@array_file){
@array = split (",", $array_record) ;

#The idea is to substitute meaningful values for column 5 based on the value of column #3. However because there are so many different values in column 3 (please note the $ #sign that requires an escape character, help so that it is not interpreted as variable.) that #calls for different values in column 5. I am thinking of putting them (columns 3 and 5) #in separate arrays. Please advise the best way to do this just so I don’t have to hard-code #every values like below.

if ($array[2] eq "23$45") {
$array[4] = "MATERNITY LEAVE";

#Also, if column 6 is greater than zero use the value in the column else use the value in #column 7 whichever is greater than zero.
if ($array[5] == 0 ) {
$array[5] = $array[6]
else
$array[5] = $array[5]
}

Here is sample output
Jasmin,Long ,23$45 ,1234A, MATERNITY LEAVE, 3, 3
David ,Malow, 3328$,7765B, COURT DUTY LEAVE, 2, 4
.
.
.
.
Susan ,Hagen, $8699 ,87564, VACATION LEAVE, 5, 5

 
Hello Hello,
My question, why do you want $array[4] based on the price (means column 3) insted of column 5 itself.
In the second case you can put all mnemonic values (short names) as keys of a hash, and meaningfull names in values.
Here is your code modified :
Code:
%myhash = ('MATLV' => 'MATERNITY LEAVE', 'VACLV' => 'VACATION LEAV', etc.) ;
@array_file = <INPUT> ;
foreach $array_record (@array_file){
@array = split (",", $array_record) ;
$array[4]=$myhash{$array[4]};
$array[5] = $array[6] if ($array[5] == 0 ) ;
# $array[5] = $array[5] has no effect
}

HTH,

Zephan
 
coulmn 3 is not actually price.

It is a mnemonic value just like columns 3, 4 or 5.

However, the value of column 5 is based on the value of column 3 and there are so many values in column 3 to put as:
%myhash = ('MATLV' => 'MATERNITY LEAVE', 'VACLV' => 'VACATION LEAV', etc.) ;
This is the thing, I am trying to avoid hard-coding 400 values of column 3 and 5.

Sorry should have explianed much better.

Thanx.
 
I think the hash idea suggested by zephan is still the way to go. If there are really 400 alternatives, then store the data in a file and have the program read it into a hash. I used __DATA__ for the hash file in this example.
Code:
#!perl
use strict;
use warnings;

my %myhash = map {split /,/} <DATA>;
chomp %myhash;

my @array_file = ( 'Jasmin,Long ,23$45 ,1234A, MATLV, 0, 3',
                   'David ,Malow, 3328$,7765B, CRTLV, 2, 4',
                   'Susan ,Hagen, $8699 ,87564, VACLV, 0, 5',
                  );

my @out;
foreach my $array_record (@array_file) {
    my @array = split([b]/\s*,\s*/[/b], $array_record); [b]#split on comma maybe with surrounding blanks[/b]
    $array[4] = $myhash{$array[2]};
    $array[5] [b]||=[/b] $array[6]; [b]#assign only if $array[5] has zero value[/b]
    push(@out, [ @array ]);
}

for (@out) {
    print join(",", @$_), "\n";
}

__DATA__
23$45,MATERNITY LEAVE
3328$,COURT DUTY LEAVE
$8699,VACATION LEAVE

[b]Output[/b]
Jasmin,Long,23$45,1234A,MATERNITY LEAVE,3,3
David,Malow,3328$,7765B,COURT DUTY LEAVE,2,4
Susan,Hagen,$8699,87564,VACATION LEAVE,5,5
 
Hi,

Your idea actually works. Thanx Mikevh.

However, following your advice to use the harsh, and in order to follow the existing organization standard, I was able to make the following effort while incorporating your idea.

#!/usr/bin/perl
use strict ;
#use warnings ;
use Date::Manip ;

my (@input) ;
my ($input_file) ;
my ($input_data) ;
my ($output_file);
my (@output);
my ($array_record);
my ($array_data);
my (%array_data);
my (@array) ;
my (@array_file);
my (@names);
my ($new_record);
my (%myhash) ;

$input_file = "levln_ac_in.txt"; #below is an example
200765,,,3/21/1996,3/22/1996,,VACATION,VAC.TAKEN OTHER GRPS,,15,,,0

$input_data = "levln_dt_in.txt"; #below is an example of contents. Note the dollar sign
TERMINATION $,VAC HRS PAY,VACATION
TERMINATION HRS,VAC HRS PAY,VACATION
UNION W PAY,UNION LV UNIONPD,OTHER
UNION W/O PAY,LWOP,LWOP
UNION W/O PAY(S/T),LWOP,LWOP

$output_file = "levln_ac_out.txt";

#check input files
(-e $input_file) || die ("input file does not exist \n") ;
(-e $input_data) || die ("input data file does not exist \n") ;

#open files
open(INPUTF, "$input_file") || die ("could not open infile\n");
open(INPUTD, "$input_data") || die ("could not open data file\n");
open(OUTPUT, ">$output_file") || die ("could not open outfile \n") ;

#put files into array and harsh
@array_file = <INPUTF> ;
%array_data = <INPUTD> ;

#Split input files and data files
@array = split(/\s*,\s*/, $array_record);
%myhash = map {split /,/} $array_data;

chomp %myhash;
chomp @array ;

foreach $array_record (@array_file) {
#Next line is to check the values in 8th element of array file - $array[7], if it is the same as the first element in harsh.
#If the same, the 8th element of array is to change to 2nd element of hash and 7th element of array is to change to 3rd element of hash.
$array[7] = $myhash{$array[1]};

#Next step assign a value of $array[9] if $[array[12] has a value of zero
$array[12] ||= $array[9] ;

#I am not so sure of what the next step does, since we are writing to a file.
push(@output, [ @array ]);

$new_record = join ',', @array;
print OUTPUT "$new_record\n";

}
close (INPUT) ;
close (OUTPUT) ;


However, this is not working. Here is the sample of output:

,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,

Please help, thanx a bunch
 
A hash consists of key/value pairs.
Where are the pairs in your file "input_data"?

TERMINATION $,VAC HRS PAY,VACATION
TERMINATION HRS,VAC HRS PAY,VACATION
UNION W PAY,UNION LV UNIONPD,OTHER
UNION W/O PAY,LWOP,LWOP
UNION W/O PAY(S/T),LWOP,LWOP


Each record has 3 fields, assuming you're splitting on the comma. How can this be a hash? Where are the key/value pairs?

How would this match up with your input record?
200765,,,3/21/1996,3/22/1996,,VACATION,VAC.TAKEN OTHER GRPS,,15,,,0
What would the output be?


 
Hello,

In the foreach loop, the purpose is to make the following changes for each record in the array of input file.

1)check the values in 8th element of input file - from:
200765,,,3/21/1996,3/22/1996,,VACATION,VAC.TAKEN OTHER GRPS,,15,,,0
$array[7]is (VAC.TAKEN OTHER GRPS)

2) compare above with all values in column 1 of input data file. For example column 1 of row 3 matches:
TERMINATION $,VAC HRS PAY,VACATION
TERMINATION HRS,VAC HRS PAY,OTHER
VAC.TAKEN OTHER GRPS,VAC HRS PAY,VACATION
UNION W PAY,UNION LV UNIONPD,OTHER
UNION W/O PAY,LWOP,LWOP
UNION W/O PAY(S/T),LWOP,LWOP

3)If column 1 of row 3 matches in the iput data , the 8th (VAC.TAKEN OTHER GRPS) element of array is to change to 2nd (VAC HRS PAY) element of input data and 7th (VACATION) element of array is to change to 3rd (OTHER) element of the row.
4)Next step assign a value of $array[9] if $[array[12] has a value of zero
$array[12] ||= $array[9] ;

5)Final value of the original record in input file:
200765,,,3/21/1996,3/22/1996,,OTHER,VAC HRS PAY,,15,,,0

5)Each record in the input file would have to go through this search and replace.

Any help will be appreciated.
 
3)If column 1 of row 3 matches in the iput data , the 8th (VAC.TAKEN OTHER GRPS) element of array is to change to 2nd (VAC HRS PAY) element of input data and 7th (VACATION) element of array is to change to 3rd (OTHER) element of the row.
The 3rd element of the "VAC.TAKEN OTHER GRPS" row is VACATION, not OTHER. Take a look at what you posted. Following the steps you describe, your final output would be
200765,,,3/21/1996,3/22/1996,,VACATION,VAC HRS PAY,,15,,,0, not
200765,,,3/21/1996,3/22/1996,,OTHER,VAC HRS PAY,,15,,,0

Is that what you meant, or am I just confused for some strange reason? [3eyes]



 
Here's a version where the hash values are 2-element arrays. This lets you have your "3 element" hash.
Again, I'm using __DATA__ for the hash and hardcoding @array_file. You could modify this to read from external files. Also I'm printing to the screen. Modify to print to file.
Code:
#!perl
use strict;
use warnings;

my %myhash;
while (<DATA>) {
    chomp;
    my ($key, @valarray) = split /,/;
    $myhash{$key} = [ @valarray ];
}

my @array_file = (
    '200765,,,3/21/1996,3/22/1996,,VACATION,VAC.TAKEN OTHER GRPS,,15,,,0',
);

my @output;
foreach my $array_record (@array_file) {
    chomp($array_record);
    my @array = split(/\s*,\s*/, $array_record);
    # array[6] is to change to 3rd DATA element.
    # array[7] is to change to 2nd DATA element.
    $array[6] = $myhash{$array[7]}[1];
    $array[7] = $myhash{$array[7]}[0];

    # Assign a value of $array[9] if $[array[12] has a value of zero 
    $array[12] ||= $array[9] ; 

    push(@output, [ @array ]);
}

print join(",", @$_), "\n" for @output;


__DATA__
TERMINATION $,VAC HRS PAY,VACATION
TERMINATION HRS,VAC HRS PAY,OTHER
VAC.TAKEN OTHER GRPS,VAC HRS PAY,VACATION
UNION W PAY,UNION LV UNIONPD,OTHER
UNION W/O PAY,LWOP,LWOP
UNION W/O PAY(S/T),LWOP,LWOP

[b]Output:[/b]
200765,,,3/21/1996,3/22/1996,,VACATION,VAC HRS PAY,,15,,,15

HTH


 
Hi Mikevh,

Sorry for not informing you earlier. I was able to get this working early yesterday through my own effort. It seems to be giving out the correct output, and the Business Analyst seems to like the output. Trust me she is a toughie. Anyway, below is the code I ended up developing. Note that there are some lines that are not necessary and the code is not the neatest. But it is working. Here is the full code and thanks very much for all your efforts.

#!/usr/bin/perl
use strict ;
#use warnings ;
use Date::Manip ;

my (@input) ;
my ($input_file) ;
my ($input_data) ;
my ($output_file);
my (@output);
my ($array_record);
my ($array_data);
my (@arrayf) ;
my (@arrayd) ;
my (@array_file);
my (@array_data);
my (@names);
my ($new_record);

$input_file = "levln_ac_in.txt";
$input_data = "levln_dt_in.txt";
$output_file = "levln_ac_out_new.txt";

#check input files
(-e $input_file) || die ("input file does not exist \n") ;
(-e $input_data) || die ("input data file does not exist \n") ;

#open input files
open(INPUTF, "$input_file") || die ("could not open infile\n");
open(INPUTD, "$input_data") || die ("could not open data file\n");
open(OUTPUT, ">$output_file") || die ("could not open outfile \n") ;

#put files into arrays
@array_file = <INPUTF> ;
@array_data = <INPUTD> ;

#Split input files and data files
@arrayf = split(",", $array_record);
@arrayd = split(",", $array_data);

foreach $array_record (@array_file) {
chomp @arrayf;
chomp @arrayd;
@arrayf = split(",", $array_record);
foreach $array_data (@array_data) {
@arrayd = split(",", $array_data);
if ($arrayf[7] eq $arrayd[0]) {
chomp $arrayd[1];
chomp $arrayd[2];
chomp $arrayf[6];
chomp $arrayf[7] ;
$arrayf[7] = $arrayd[1] ;
$arrayf[6] = $arrayd[2];
}
}

if ($arrayf[13] > 0 ){
$arrayf[9] = $arrayf[13] ;
chomp $arrayf[9] ;
chomp $arrayf[13] ;
}

$new_record = join ',', @arrayf;
print OUTPUT "$new_record\n";

}
close (INPUT) ;
close (OUTPUT) ;
 
Glad you came up with something that seems to work for you and that you're happy with.

Without looking at the code too closely, I can see that there are indeed some lines that are not necessary, as you say. In particular, you've got a lot of unnecessary chomps.

Also, at one point you're splitting a variable that hasn't even been initialized yet.

While having code that works may seem like the most important thing, I encourage you to look this over and see how it could be made neater. This really does pay off in the long run.

Congrats once again on getting it working. :)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top