evenstar
evenstar

Reputation: 3

How can I add all the numbers in multiple arrays and write into another array in Perl

Actually in this assignment, I need to combine 12 input file datas into only one output file. Each input file like this,

ACME A  0   2
ACME A  1   0
ACME A  2   0
ACME A  3   0
ACME A  4   0
ACME A  5   0
ACME A  6   0

In output file ı want to obtain, all related data like this;

**********************************************************************
2017-02-03 0 ACME A 0   2   4   43  4   4   25  4   3   26  4   4   18
2017-02-03 0 ACME A 0   2   4   43  4   4   25  4   3   26  4   4   0
2017-02-03 0 ACME A 0   2   4   43  4   4   25  4   3   26  4   4   0
2017-02-03 0 ACME A 0   2   4   43  4   4   25  4   3   26  4   4   1

Here is my full code.

#! /usr/bin/perl -w

#compiler profilleri
use strict;
use warnings;

sub trim($)
{
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}

#dosya locationları

my $input_file="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_01.txt";
my $input_file1="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_06.txt";
my $input_file2="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_11.txt";
my $input_file3="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_16.txt";
my $input_file4="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_21.txt";
my $input_file5="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_26.txt";
my $input_file6="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_31.txt";
my $input_file7="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_36.txt";
my $input_file8="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_41.txt";
my $input_file9="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_46.txt";
my $input_file10="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_51.txt";
my $input_file11="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_56.txt";

my $output_file="C:/Perl64/output/denemecik.txt";

#komutlar######
my $ne;  my @cc_type; my @cc_count;
my @cc_count1; my @cc_count2; my @cc_count3; my @cc_count4; my @cc_count5;
my @cc_count6; my @cc_count7; my @cc_count8; my @cc_count9; my @cc_count10; my @cc_count11;
my @total; my $i;

my @count=0; my @count1=0; my @count2=0; my @count3=0; my @count4=0; my @count5=0; my @count6=0;
my @count7=0; my @count8=0; my @count9=0; my @count10=0; my @count11=0;

my $date='sbc_cause_comp_intraday_2017-02-03_00_01';
my $date1=substr($date,24,10);
my $hour=substr($date,35,1);
#print ($hour);

open INPUT, "< $input_file" or die "$0: open of $input_file failed, error: $! \n";
open INPUT1, "< $input_file1" or die "$0: open of $input_file1 failed, error: $! \n";
open INPUT2, "< $input_file2" or die "$0: open of $input_file2 failed, error: $! \n";
open INPUT3, "< $input_file3" or die "$0: open of $input_file3 failed, error: $! \n";
open INPUT4, "< $input_file4" or die "$0: open of $input_file4 failed, error: $! \n";
open INPUT5, "< $input_file5" or die "$0: open of $input_file5 failed, error: $! \n";
open INPUT6, "< $input_file6" or die "$0: open of $input_file6 failed, error: $! \n";
open INPUT7, "< $input_file7" or die "$0: open of $input_file7 failed, error: $! \n";
open INPUT8, "< $input_file8" or die "$0: open of $input_file8 failed, error: $! \n";
open INPUT9, "< $input_file9" or die "$0: open of $input_file9 failed, error: $! \n";
open INPUT10, "< $input_file10" or die "$0: open of $input_file10 failed, error: $! \n";
open INPUT11, "< $input_file11" or die "$0: open of $input_file11 failed, error: $! \n";

open OUTPUT, "> $output_file" or die "$0: open of $output_file failed, error: $! \n";

print OUTPUT ("**********************************************************************\n");
while ( defined ($_=<INPUT>) )
{   

    my $line = $_;
    my ( $ne, $cc_type, $cc_count) = split ('\t',$line);
    my $count=trim($cc_count);
    print("$ne\n");
    while ( defined ($_=<INPUT1>) )
    {
        my $line1 = $_;
        my ( undef, undef, $cc_count1) = split ('\t',$line1);
        my $count1=trim($cc_count1);
        #print("$count1\n");
        while ( defined ($_=<INPUT2>) )
        {
           my $line2 = $_;
           my ( undef, undef, $cc_count2) = split ('\t',$line2);
           my $count2=trim($cc_count2);
           #print("$cc_count2\n");
           while ( defined ($_=<INPUT3>) )
            {
                my $line3 = $_;
                my ( undef, undef, $cc_count3) = split ('\t',$line3);
                my $count3=trim($cc_count3);
                #print("$cc_count3\n");
                while ( defined ($_=<INPUT4>) )
                {
                     my $line4 = $_;
                     my ( undef, undef, $cc_count4) = split ('\t',$line4);
                     my $count4=trim($cc_count4);
                    # print("$cc_count4\n");
                     while ( defined ($_=<INPUT5>) )
                     {
                        my $line5 = $_;
                        my ( undef, undef, $cc_count5) = split ('\t',$line5);
                        my $count5=trim($cc_count5);
                        #print("$cc_count5\n");
                        while ( defined ($_=<INPUT6>) )
                        {
                            my $line6 = $_;
                            my ( undef, undef, $cc_count6) = split ('\t',$line6);
                            my $count6=trim($cc_count6);
                            #print("$cc_count6\n");
                            while ( defined ($_=<INPUT7>) )
                            {
                                my $line7 = $_;
                                my ( undef, undef, $cc_count7) = split ('\t',$line7);
                                my $count7=trim($cc_count7);
                                #print("$cc_count7\n");
                                while ( defined ($_=<INPUT8>) )
                                {
                                    my $line8 = $_;
                                    my ( undef, undef, $cc_count8) = split ('\t',$line8);
                                    my $count8=trim($cc_count8);
                                    #print("$cc_count8\n");
                                    while ( defined ($_=<INPUT9>) )
                                    {
                                         my $line9 = $_;
                                         my ( undef, undef, $cc_count9) = split ('\t',$line9);
                                         my $count9=trim($cc_count9);
                                         #print("$cc_count9\n");
                                         while ( defined ($_=<INPUT10>) )
                                         {
                                             my $line10 = $_;
                                             my ( undef, undef, $cc_count10) = split ('\t',$line10);
                                             my $count10=trim($cc_count10);
                                             #print("$cc_count10\n");
                                             while ( defined ($_=<INPUT11>) )
                                             {
                                                my $line11 = $_;
                                                my ( undef, undef, $cc_count11) = split ('\t',$line11);
                                                my $count11=trim($cc_count11);
                                                #print("$cc_count11\n");

                                                for( $i=0; $i< scalar @count; $i++ )
                                                {
                                                  $total[$i] = $count[$i] + $count1[$i] + $count2[$i] + $count3[$i] + $count4[$i] + $count5[$i] + $count6[$i] + $count7[$i] + $count8[$i] + $count9[$i] + $count10[$i] + $count11[$i];
                                                #   print("@total\n");
                                                }
                                                 print OUTPUT ("$date1 $hour $ne $cc_type   $count  $count1 $count2 $count3 $count4 $count5 $count6 $count7 $count8 $count9 $count10    $count11 $total\n");   
                                               #   print("@total\n");


                                             }
                                          }
                                    }
                                 }
                               }
                        }
                    }
                }
            }
        }
    }           

}

close OUTPUT;
close INPUT;
close INPUT1;
close INPUT2;
close INPUT3;
close INPUT4;
close INPUT5;
close INPUT6;
close INPUT7;
close INPUT8;
close INPUT9;
close INPUT10;
close INPUT11;

I am a newbie in perl. Can you please help me to write this code more logically. For example how can ı read multiple input files without using a lot of while loop and writing into only one output file. Right now, output file shows only first row as true, and the remaining rows just the iteration of the first one, so it is not true. The second problem is,I dont know how to add number values in one row properly. For example I want to add 2 to 18 ( 12 values) and write this value as a final column in output file. Thanks in advance.

Upvotes: 0

Views: 94

Answers (4)

ikegami
ikegami

Reputation: 385789

sub sum { my $sum; $sum += $_ for @_; $sum }

my $sum = sum
   @count,
   @count1,
   ...
   @count10,
   @count11;

Rather than having a ton of arrays, you should probably have an array of arrays (or hash of arrays).

sub sum { my $sum; $sum += $_ for @_; $sum }

while (<>) {
    chomp;
    my @fields = split /\t/;
    push @aoa, \@fields;
}

my $sum = sum map { @$_[4..15] } @aoa;

or just

my $sum;
while (<>) {
    chomp;
    my @fields = split /\t/;
    $sum += $_ for @fields[4..15];
}

(There appears to be 17 columns, yet you say there are 16, so I'm assuming the whitespace beteween ACME A isn't a tab. Adjust the indexes as needed.)

Upvotes: 2

Borodin
Borodin

Reputation: 126722

This solution reads the input file and splits each line, storing the result as an array of arrays. A pair of map calls reduces that data to an array of column totals

There is clearly an issue with some of the data not being numeric, so each column is tested to see if it contains any non-numeric values, in which case undef is provided as the total

I have used first from List::Util even though all would be clearer because it is only more recent versions of the module that provide the latter

I have tested this by creating a file with two copies of your line of data. (Please provide a more comprehensive data sample in the future.)

The program expects the path to the input file as a parameter on the command line

I have used Data::Dumper only to reveal the result of the calculation

use strict;
use warnings 'all';

use List::Util   qw/ first sum /;
use Scalar::Util qw/ looks_like_number /;

our @ARGV = 'data.txt';

my @data = map [ split ], <>;

my @totals = map {
    my $i = $_;
    my @column = map { $_->[$i] }  @data;
    defined( first { not looks_like_number($_) } @column) ? undef : sum(@column);
} 0.. $#{$data[0]};

use Data::Dumper;
print Dumper \@totals;

If you are using a more recent copy of List::Util that provided all, then you can make use of it by changing the use statement to

use List::Util qw/ all sum /;

and rewriting the defined( ... ) line to

all { looks_like_number($_) } @column ? sum(@column) : undef;

output

$VAR1 = [
          undef,
          '0',
          undef,
          undef,
          '0',
          '4',
          '8',
          '86',
          '8',
          '8',
          '50',
          '8',
          '6',
          '52',
          '8',
          '8',
          '36'
        ];

Upvotes: 1

Sobrique
Sobrique

Reputation: 53478

OK, any point you start numbering variables, you should be seriously thinking about using an array instead.

And that goes if they're arrays too. So you might be able to use an array of arrays, but it's unclear quite what you're actually putting into $count.

But for your problem, I'd tackle it like this:

#!/usr/bin/env perl

use strict;
use warnings;


#iterate the DATA filehandle below, line by line. 
while ( <DATA> ) {
    #split the row on whitespace. 
    my @row = split; 
    my $sum;
    #iterate each field
    foreach my $value ( @row ) {  
        #increment the sum by the value, if it's numeric. 
        if ( $value =~ m/^\d+$/ ) { 
           $sum += $value; 
        }
    }
    #print the sum for this row. 
    print $sum,"\n";
}


__DATA__
2017-02-03 0 ACME A 0   2   4   43  4   4   25  4   3   26  4   4   18

And that way, you don't actually need an array of arrays at all.

Note - you can scale this up to your input, probably by just using <> as your input file handle, which reads files specified on command line or STDIN rather than the __DATA__ filehandle.

Upvotes: 4

Sinan &#220;n&#252;r
Sinan &#220;n&#252;r

Reputation: 118128

The script below will sum all numeric columns in the data individually and put the sums in an hash called %counts. The keys of the hash will be variable names (which I would normally infer from the header of the file, but you do not provide it, so I made them up).

#!/usr/bin/env perl

use strict;
use warnings;

use List::Util qw( sum );

my %counts;

while (my $line = <DATA>) {
    my (@cols) = split ' ', $line;
    my @numeric = map [$_, $cols[$_]], grep $cols[$_] =~ /^[0-9]+\z/, 0 .. $#cols;
    for my $entry ( @numeric ) {
        $counts{ 'VAR' . $entry->[0] } += $entry->[1];
    }
}

use Data::Dumper;
print Dumper \%counts;

printf "Grand total = %d\n", sum values %counts;

__DATA__
2017-02-03 0 ACME A 0   2   4   43  4   4   25  4   3   26  4   4   18
2017-02-03 0 ACME A 0   2   4   43  4   4   25  4   3   26  4   4   18
2017-02-03 0 ACME A 0   2   4   43  4   4   25  4   3   26  4   4   18
2017-02-03 0 ACME A 0   2   4   43  4   4   25  4   3   26  4   4   18
2017-02-03 0 ACME A 0   2   4   43  4   4   25  4   3   26  4   4   18

Output:

$ perl s.pl                                     
$VAR1 = {                                       
          'VAR7' => 215,                        
          'VAR15' => 20,                        
          'VAR8' => 20,                         
          'VAR11' => 20,                        
          'VAR14' => 20,                        
          'VAR10' => 125,                       
          'VAR12' => 15,                        
          'VAR1' => 0,                          
          'VAR4' => 0,                          
          'VAR5' => 10,                         
          'VAR6' => 20,                         
          'VAR9' => 20,                         
          'VAR16' => 90,                        
          'VAR13' => 130                        
        };                                      
Grand total = 705                               

Upvotes: 2

Related Questions