0

I have a data file looks like :

1 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 
2 4 5 8 9 10 13 17 19 29 30 32 33 50 700 800 900 950 

first I want to insert space among each 3 identical values keeping each three identical numbers together in one colum by looking at the first row :

1 1 1  1 1 1  1 1  2 2 2  2  3 3 3  3 3 3 
2 4 5  8 9 10  13 17  19 29 30  32  33 50 700  800 900 950

and then I want to subtract the first value from the last one within each new column at second row ( but if there was only one value at a specific column(here the forth column at second row), then the last value from the previous column should be subtracted from that value(32-30)) while keeping one unique number out of each column from the first row. so the final data should be like this:

1 1 1 2 2 3 3
3 2 4 11 2 667 150 

any suggestion please? meanwhile I should mention my real data is indeed huge and I want to group each 5 unique values at first row. I may want to change the size of group . So I need the script to be flexible ..

  • Tried anything ? – 123 Jan 29 '16 at 14:02
  • 1
    I read your requirements about 10 times before I understood them. (Perl is definitely the tool for this, by the way.) – Wildcard Jan 29 '16 at 14:49
4

Perl to the rescue!

#!/usr/bin/perl
use warnings;
use strict;

my $group_size = 3;

my @first = split ' ', <>;

my @groups;
my $start_index = 0;
while ($start_index < @first) {
    my $step = 1;
    while ( $step < $group_size
            && $start_index + $step < @first
            && $first[$start_index] == $first[ $start_index + $step ]
          ) {
        ++$step;
    }
    push @groups, $step;
    print $first[$start_index], ' ';
    $start_index += $step;
}
print "\n";

my @numbers = split ' ', <>;

my $last;
for my $size (@groups) {
    my @group = splice @numbers, 0, $size;
    my $value = $group[-1] - $group[0];
    $value = $group[0] - $last if 1 == $size;
    $last = $group[-1];
    print $value, ' ';
}
print "\n";

You haven't specified what should happen if the very first group has just one member.

  • choroba that wonts happen. – zara Jan 29 '16 at 16:36
  • @zara: Just specify the data file name as the parameter of the program. – choroba Jan 29 '16 at 16:51
  • 1
    @zara: T.I.T.S. = Try It To See. – choroba Jan 29 '16 at 16:52
  • should I do like this to make it run? ../yourscript.pl data.txt – zara Jan 29 '16 at 16:55
  • @zara: If you first make the script executable by chmod u+x program.pl, then yes – choroba Jan 29 '16 at 16:55
1

This is similar to choroba's answer

$ cat file
1 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 
2 4 5 8 9 10 13 17 19 29 30 32 33 50 700 800 900 950 

$ perl -ane '
    if ($. == 1) {
        for (($n,$i,$j) = (1,0,0); $j < @F; $n++, $j++) {
            if ($n == 3 || $F[$j] != $F[$j+1]) {
                $i-- if $i == $j;
                push @pairs, [$i, $j];
                $n = 0;
                $i = $j + 1;
            }
        }
        printf "%d ", $F[ $_->[1] ] for @pairs;
    }
    else {
        printf "%d ", $F[ $_->[1] ] - $F[ $_->[0] ] for @pairs;
    }
    print "\n";
' < file
1 1 1 2 2 3 3 
3 2 4 11 2 667 150 

For the first line of input ($. == 1) it calculates the list of pairs of indices you are interested in. This works out to:

[[0, 2], [3, 5], [6, 7], [8, 10], [10, 11], [12, 14], [15, 17]]
  • does your script works in case if I want to change the group size from 3 into 20? – zara Jan 29 '16 at 22:09
  • meanwhile my real data is huge and I need to specify input file in a seperate file than script . how it is possible by your script? – zara Jan 29 '16 at 22:10
  • first comment: change $n == 3 to $n == 20. second comment: I don't understand what you're saying -- possibly you want to change < file to < the_real_name_of_your_input_file – glenn jackman Jan 29 '16 at 22:31
  • i mean how should i run this? should i do like: perl yourscript.pl input.txt > out.txt ? – zara Jan 29 '16 at 22:34
  • I do not know how to run I copied exactly what you wrote in script in to a .plfile and i tried to run.. but wont work :( – zara Jan 29 '16 at 22:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.