0

I have a text file with list of numbers separated by blank line as given below- i want to add all the first (20.187+19.715+20.706...) , second elements (15.415+14.726+15.777) and so on to get the total of each element 1st,2nd,3rd etc

20.187 15.415  8.663  6.001  6.565  6.459  6.564 ..

19.715 14.726  8.307  5.833  6.367  6.089  6.444 ..

20.706 15.777  9.185  6.546  7.327  7.172  7.084 ...

since they are *not arranged in columns* how could i add up the elements of the array.

5
  • 1
    You edited to emphasize "not arranged in columns" ... I'm failing to understand this. You're asking how to add together all the Nth elements of each line (which all the answers below demonstrate). How is that "not arranged in columns" ? Commented Mar 8, 2011 at 18:57
  • @Brian Roach: My guess is he means that the columns are not fixed-width. However, split operates on delimiters, not fixed widths. Commented Mar 8, 2011 at 19:00
  • the numbers are arranged in more than one line if they are many say 300 or so seperated by blank spaces , so in each block/group ,each column can have more than one number from each group..so adding it column wise i thought wont work Commented Mar 8, 2011 at 19:04
  • 1
    Are you certain you're not just seeing line wrap when editing/displaying the file? If not, we'd (you'd) need to know what denotes a "block/group" in the file. Commented Mar 8, 2011 at 19:11
  • Ok ... got it now. The blank line is your group delimiter. See my edited answer below. Commented Mar 8, 2011 at 19:26

4 Answers 4

6

Use split to get all the fields. Keep track of a running total in an array (the indexed of which being mapped to the columns in your file).

Something like this:

while (<$file>)
{
  chomp;
  my $index = 0;
  $total[$index++] += $_ for split;
}

Note that split splits on whitespace by default. You can use other delimiters if you like.


EDIT: This answer is sadly useless, now that the question has been clarified. Use Brian Roach's answer instead.

Sign up to request clarification or add additional context in comments.

7 Comments

I had no idea about that syntax for for. Sweet.
@Mat: Any of the loop statements have this capability, where you can modify any single statement's execution to flow based on the loop. If you want multiple statements, obviously you need to use a block. (You CAN also use do { # block } while $condition and similar, but sometimes you get different behavior. do-while will execute once, like in C, but statement-while will work like a normal while loop. So I usually just use either while { #block } or statement while $condition UNLESS I specifically need do-while functionality. Clear as mud? :-)
@Mat: Oh, and you can't use any loop variable besides $_ when you do loop suffixes on single statements. That's the only pitfall.
I would argue that another pitfall is using funky perl syntax for no performance gain while possibly confusing the next bloke who has to look at your code ;)
How else do you think I guarantee my job security? ;-)
|
5

EDIT: From the clarified question, Need to deal with the blank lines and the possibility that a series of numbers is broken onto multiple lines.

my @totals;
my @currentVals;

while (my $line = <FILE>)
{
    chomp($line);
    if ($line eq "")
    {
        for ($i = 0; $i < @currentVals; $i++)
        {
            @totals[$i] += @currentVals[$i];
        }    
        @currentVals = ();
    }
    else
    {
        push @currentVals,  split(' ', $line);
    }

}

This should do what you're looking for. You need to keep adding onto the currentVals array until you hit a blank line, then do the math.

1 Comment

@user631148: THIS is the correct answer, now that the question has been clarified. Please disregard my answer.
3
use strict;
use warnings;

# Paragraph mode (so that blank lines become our input delimiter).
local $/ = "\n\n";

my @totals;

while (<>){
    my $i;
    $totals[$i++] += $_ for split;
}

2 Comments

That is certainly the "perl way to do it". Except you used a comment to actually explain the trick ;)
Oh snap. That will definitely do it! (+1)
2

You could try something like this:

my @sum;
while (<>) {
    chomp;
    my @items = split /\s+/;
    for (my $i=0; $i<@items; $i++) {
        $sum[$i] += $items[$i];
    }
}

$sum[$i] will contain the total of column $i.

Or, slightly more 'perlish':

my @sum;
while (<>) {
    chomp;
    my @items = split;
    for my $i (0 .. $#items) {
        $sum[$i] += $items[$i];
    }
}

2 Comments

This answer is probably a lot clearer than mine anyway, now that I look at it. :-) (+1) I'm taking advantage of a lot of Perl defaults, like split with no arguments and single-statement-for.
You got my (+1) - the C-style for loop always looks weird (IMO) in perl.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.