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 TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Reading Text File into Array and performing operations 2

Status
Not open for further replies.

stevio

Vendor
Jul 24, 2002
78
AU
I've got a set of data in a text file which looks like the following:

Data1 Data2 Data3
0 0 23
0 1 0
0 2 3
...
1 0 45
1 1 23
1 2 0

The number of rows is totally variable
There are 2 halves of data separated by Data1 and the change is reflected when it changes from 0 to 1 (i.e. Data1 can only be 0 or 1)
Data2 does not always start from 0, but usually does and increments are not necessarily by one or sequential. The Data2 numbers are exactly a mirror of each other from the two halves.

What I want to do is to go thru each line and find the Data2 value in the top half, and see if the Data3 value is > 0. If it is, then find the corresponding Data2 value in the bottom half and see if it greater than 0. If they are both greater than zero, then output the results to a text file

So in our example above, the result match would be

0 0 23
1 0 45

So far, I have the following:

Code:
use strict;
use warnings;

LINE:
while (<DATA>) {
    chomp;
    my $line = $_;
    
    my ($num) = ($line =~ m{^\d+\s+\d+\s+(\d+)})
        ? $1
        : do {warn "Line does not match pattern: $line"; next LINE};
    
        if ($num > 0) {
        print "$line\n";
    }
}

__DATA__
Data1   Data2     Data3
0        0          23
0        1           0
0        2           3
1        0          45
1        1          23
1        2           0

This currently finds which values have Data3 > 0. I can't work out the logic to search thru Data2 for match values.

Any ideas would be appreciated.
 
Perl:
#!/usr/bin/perl

use strict;
use warnings;

my %data;

while (<DATA>) {
   next if ($. == 1);
   chomp;
   my ($d1, $d2, $d3) = split;
   $data{$d1}->{$d2} = $d3;
}

foreach my $d2 (sort keys %{$data{0}}) {
   if ($data{0}->{$d2} > 0 && $data{1}->{$d2} > 0) {
      print "0\t$d2\t$data{0}->{$d2}\n";
      print "1\t$d2\t$data{1}->{$d2}\n";
   }
}

__DATA__
Data1   Data2     Data3
0        0          23
0        1           0
0        2           3
1        0          45
1        1          23
1        2           0
I've used a hash as a way of keying the two values together, but you could use an array if you prefer...

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
Code:
use strict;
use warnings;
my(@fields,%nonzero);
$_=<DATA>;  #skip heading line
while(<DATA>){
  @fields=split;
  last if$fields[0];
  $nonzero{$fields[1]}=$fields[2]if$fields[2];
}
if(exists$nonzero{$fields[1]}&&$fields[2]){
  print"0\t$fields[1]\t$nonzero{$fields[1]}\n";
  print"1\t$fields[1]\t$fields[2]\n";
}
while(<DATA>){
  @fields=split;
  if(exists$nonzero{$fields[1]}&&$fields[2]){
    print"0\t$fields[1]\t$nonzero{$fields[1]}\n";
    print"1\t$fields[1]\t$fields[2]\n";
  }
}
__DATA__
Data1   Data2     Data3
0        0          23
0        1           0
0        2           3
1        0          45
1        1          23
1        2           0

Franco
: Online engineering calculations
: Magnetic brakes for fun rides
: Air bearing pads
 
Thanks to both of you especially for the rapid reply. Works a treat :)

Star each
 
Hey guys, just wondering if I could ask a further question.

How do I search for these numbers if they are within section of a file

So the section looks like this:

---- Section 1 ----
Data1 Data2 Data3
0 0 23
0 1 0
0 2 3
1 0 45
1 1 23
1 2 0
.....
Data4 Data5 Data6

The headings Data1 -> Data6 are unique.

So basically, I want to process everything in between the headings.
 
You can use the bistable capabilities of the range operator ..
Perl:
if (/^Data1/ .. /^Data4/) {
   # do stuff to selected records
}
The condition goes to TRUE when it reads the record starting with 'Data1' and stays TRUE until it encounters the record beginning with 'Data4'. I'll leave you to figure out what goes in between...

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top