in reply to Count in intervals
use strict; use warnings; use constant { LOW => 0, HIGH => 1, VALUE => 2 }; my $FILE1 = <<'EOF'; so 10 0.05 so 11 0.03 so 25 0.15 so 35 0.3 so 36 0.25 so 37 1 ge 14 0.12 ge 20 0.4 EOF my $FILE2 = <<'EOF'; so 10 20 so 30 40 ge 10 30 EOF my %ranges; # Read FILE2 and create a useful datastructure. open my $ifh2, '<', \$FILE2 or die $!; while( <$ifh2> ) { chomp; next unless length; my( $cat, $low, $high ) = split /\s+/, $_; push @{$ranges{$cat}}, [ $low, $high ]; } close $ifh2; # Read FILE1 and increment counters within our datastructure. open my $ifh1, '<', \$FILE1 or die $!; while( <$ifh1> ) { chomp; next unless length; my( $cat, $target, $value ) = split /\s+/, $_; foreach my $range ( @{$ranges{$cat}} ) { $range->[VALUE] += $value if $target >= $range->[LOW] && $target <= $range->[HIGH]; } } # Dump the information we need from our datastructure. while( my( $cat, $range ) = each %ranges ) { print "$cat $_->[VALUE]\n" foreach @$range; }
This constructs a data structure that looks like this:
%ranges = ( 'ge' => [ [ 10, 30, '0.52' ] ], 'so' => [ [ 10, 20, '0.08' ], [ 30, 40, '1.55' ] ] );
Once the ranges are created, FILE1 can be read line by line, and given its general category, we will iterate over the various ranges within that category, incrementing the counter any time we determine that this line of FILE1 fits within a range.
Here's the sample output:
so 0.08 so 1.55 ge 0.52
Dave
|
|---|