I have a text file, looking similar to this:
1 Bob J Smith 3 4 2 1 10 8
2 James Miller 5 3 82 3 44 1
3 ...
What I'm trying to achieve is to only add the numbers in each row and give total per person. But has to skip past the first number (that is before the name) and text and only compute numbers. My @lines
array holds the file I need to work with.
my $total;
my @row;
foreach(@lines){
@row=split;
$total=0;
$total+=$_ for @row[3..$#row];
print "$row[0]: $total\n";
}
print "$row[0]: $total\n";
Reading a file into an array and then iterating over the array isn't generally an improvement over just iterating over the file. You shouldn't read the whole file into memory unless you particularly need to for some reason like requiring random access to the data
Your data format isn't very usable unless you actually have tabs separating the name from the surrounding fields. Otherwise there is no way to distinguish parts of the name from the rest of the fields
This program works by repeatedly adding together the last two fields of each line until the last field but one isn't numeric. It assumes the last field of every line is always numeric and doesn't make any checks for this
use strict;
use warnings 'all';
while ( <DATA> ) {
my @fields = split;
while ( $fields[-2] =~ /\A\d+\z/ ) {
push @fields, pop(@fields) + pop(@fields);
}
print "@fields\n";
}
__DATA__
1 Bob J Smith 3 4 2 1 10 8
2 James Miller 5 3 82 3 44 1
1 Bob J Smith 28
2 James Miller 138
Or use regular expressions to divide each line into name and numbers and then total the numbers.
while (<DATA>)
{
chomp;
next if /^$/;
my $total = 0;
/\d+ ([A-Za-z ]+) ([\s\d]+)$/;
my @numbers = split(' ', $2);
$total += $_ for (@numbers);
print "$1: $total\n";
}
__DATA__
1 Bob J Smith 3 4 2 1 10 8
2 James Miller 5 3 82 3 44 1
3 Allan X Smith 5 4 82 3 44 2
Possibly simpler and more straight forward:
use strict;
use warnings;
use List::Util 'sum';
while ( <DATA> ) {
my @row = split;
print shift @row, ' '; # print row number
while (@row and $row[0] !~ /^\d+$/) { # print name
print shift @row, ' ';
}
print sum(@row, 0), $/;
}
__DATA__
1 Bob J Smith 3 4 2 1 10 8
2 James Miller 5 3 82 3 44 1
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.