Showing posts with label perl-hashes. Show all posts

Sorting a file with related lines

I have a file in which first row contains the number and second row contains a statement associated with it and so on like the below example:
12
stat1 
18
stat2
15
stat3
I need to print the output like sorting in descending order of numbers along with the statement related to it. So that the output should look like:
Time = 18
Stat = stat2
Time = 15
Stat = stat3
Time = 12
Stat = stat1
Below is the perl command that I have written which does the needed thing.
perl -lne 'if(/^\d+/){$k=$_}
           else{$x{$k}=$_}
           END{ 
               for(sort {$b<=>$a} keys %x){ 
               print "time=$_\nStat=$x{$_}";}
           }' file
time=18
Stat=stat2
time=15
Stat=stat3
time=12
Stat=stat1
Note:Precondition is time will come first and then the statement associated with it. 
Below is the explanation.

1. So store in a variable $k if the line start with a decimal point number.
2. Else case it is nothing but the statement. So store this line as a value to the previous stored $k.
   After parsing complete file.sort the keys of the hash in descending order by
3. sort  $b<=>$a and then print each and ever key and value in needed format.
Also please note:
1. sort $a<=>$b will sort the numbers in ascending order.
2. sort $b<=>$a will sort the numbers in descending order

Summing up column values based upon ranges in another file

File 1 has ranges 3-9, 2-6 etc
    3 9
    2 6
    12 20

File2 has values: column 1 indicates the range and column 2 has values.
    1 4
    2 4
    3 5
    4 4
    5 4
    6 1
    7 1
    8 1
    9 4

I would like to calculate the sum of values (file2, column2) for ranges in file1). Eg: If range is 3-9, then sum of values will be 5+4+4+1+1+1+4 = 20

Below is the script for doing the same:

use strict;
use warnings;
use feature qw( say );

use List::Util qw( sum );
my $file1 = 'file1.txt';
my $file2 = 'file2.txt';

my @file2;
{   
   open(my $fh, '<', $file2)
      or die "Can't open $file2: $!\n";
   while (<$fh>) {
      my ($k, $v) = split;
      $file2[$k] = $v;
   }
}

{   
   open(my $fh, '<', $file1)
      or die "Can't open $file1: $!\n";
   while (<$fh>) {
      my ($start, $end) = split;
      say sum grep defined, @file2[$start .. $end];
   }
}