1

我有一个如下所示的 CSV 文件:

1.0,25,some_value,01
1.0,25,some_value,01
1.0,10,some_value,02
1.0,10,some_value,02
1.0,3,some_value,03
1.0,3,some_value,03

我正在$sum使用这个 Perl 程序将第二列的值累积到标量中:

use strict;
use warnings;

my $sum = 0;
my $i = 0;
my @cols;

while (my $line = <STDIN>) {
  chomp $line;
  push @cols, [ split ",", $line ];
  $sum += $cols[$i][1];
  $i++;
}

print "$sum\n";

这将得到总和76,即第二列中所有值的总和。

如果您参考上面的 CSV 文件,最后一列代表一个 ID。我真正需要的是获得最后一列第四列中每个 ID 的第二列的总和。ID 的第二列之和为0150,ID02为 20,ID03为 6。

我不确定从哪里开始实现这一点,或者它是否可以用于我的代码。

4

2 回答 2

2

您所要做的就是使用散列来存储每个唯一 ID 的总和:

use strict;
use warnings;

my %sum; # key: the unique id, value: the sum
while (my $line = <STDIN>) {
    chomp $line;
    my @cols = split /,/, $line;
    $sum{$cols[3]} += $cols[1];

}

for (sort { $a <=> $b } keys %sum) {
    print "$_: $sum{$_}\n";
} 

这将打印:

01: 50
02: 20
03: 6
于 2013-11-08T02:17:35.520 回答
2

您的代码将整个输入放入 array @cols。当您只需要一列的总和时,这会极大地浪费内存。

你的程序可以写

my $sum;
while (my $line = <STDIN>) {
  my @fields = split /,/, $line;
  $sum += $fields[1];
}

这很容易修改以使用散列对总和进行分类。此代码使用最后一个字段作为键来标识应按第二个字段的值递增的散列元素。

my %sums;
while (my $line = <DATA>) {
  chomp $line;
  my @fields = split /,/, $line;
  $sums{$fields[-1]} += $fields[1];
}

use Data::Dump;
dd \%sums;

输出

{ "01" => 50, "02" => 20, "03" => 6 }
于 2013-11-08T02:43:04.533 回答