2

我有一个格式如下的输入文件

ant,1
bat,1
bat,2
cat,4
cat,1
cat,2
dog,4

我需要为每个键(column1)聚合 col2,所以结果是:

ant,1
bat,3
cat,7
dog,4

其他注意事项:

  1. 假设输入文件已排序
  2. 输入文件非常大(大约1M行),所以我不想使用数组并占用内存
  3. 每个输入行都应该在我们读取它时进行处理,并移至下一行
  4. 我需要将结果写入 outFile
  5. 我需要在 Perl 中执行此操作,但伪代码或算法会有所帮助

谢谢!

这就是我想出的......想看看这是否可以写得更好/优雅。

open infile, outFile

prev_line = <infile>;
print_line = $prev_line;

while(<>){
   curr_line = $_;

   @prev_cols=split(',', $prev_line);
   @curr_cols=split(',', $curr_line);

   if ( $prev_cols[0] eq $curr_cols[0] ){
      $prev_cols[1] += curr_cols[1];
      $print_line = "$prev_cols[0],$prev_cols[1]\n";
      $print_flag = 0;
   }
   else{
      $print outFile "$print_line";
      $print_flag = 1;
      $print_line = $curr_line;
   }
   $prev_line = $curr_line;
}

if($print_flag = 1){
   print outFile "$curr_line";
}   
else{
   print outFile "$print_line";
}
4

3 回答 3

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

my %a;
while (<>) {
    my ($animal, $n) = /^\s*(\S+)\s*,\s*(\S+)/;
    $a{$animal} += $n if defined $n;
}
print "$_,${a{$_}}\n" for sort keys %a;

这段简短的代码让您有机会学习 Perl 出色的哈希工具,如%a. 哈希是 Perl 的核心。没有它们,一个人真的无法写出流利的 Perl。

顺便观察一下,代码执行了 Perl 有趣的自动生存功能。第一次在输入流中遇到特定动物时,不存在计数,因此 Perl 隐含地假定预先存在的计数为零。因此,+=操作员不会失败,即使它看起来应该失败。它只是在第一个实例中添加到零。

另一方面,可能不仅数据的数量而且动物的数量都非常大,以至于人们不想存储散列%a。在这种情况下,您仍然可以计算总数,前提是数据在输入中按动物排序,就像在您的示例中一样。在这种情况下,类似下面的东西可能适合(尽管遗憾的是它不像上面的那么整洁)。

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

my $last_animal = undef;
my $total_for_the_last_animal = 0;

sub start_new_animal ($$) {
    my $next_animal = shift;
    my $n = shift;
    print "$last_animal,$total_for_the_last_animal\n"
      if defined $last_animal;
    $last_animal = $next_animal;
    $total_for_the_last_animal = $n;
}

while (<>) {
    my ($animal, $n) = /^\s*(\S+)\s*,\s*(\S+)/;
    if (
        defined($n) && defined($animal) && defined($last_animal)
          && $animal eq $last_animal
    ) { $total_for_the_last_animal += $n; }
    else { start_new_animal $animal, $n; }
}
start_new_animal undef, 0;
于 2012-06-08T01:40:43.377 回答
1

使用 Perl 的awk模式

  • -一种

-n与 a或一起使用时打开自动拆分模式-p。对数组的隐式split命令是在or产生@F的隐式循环中的第一件事。while-n-p

perl -ane 'print pop(@F), "\n";'

相当于

while (<>) {
  @F = split(' ');
  print pop(@F), "\n";
}

可以使用 指定备用分隔符-F

剩下的就是将总和累加到散列中并打印出来。

$ perl -F, -lane '$s{$F[0]} += $F[1];
    END { print "$_,$s{$_}" for sort keys %s }' input

输出:

蚂蚁,1
蝙蝠,3
猫,7
狗,4
于 2012-06-08T02:49:22.007 回答
0

这在 perl 中是微不足道的。循环文件输入。用逗号分割输入行。对于第一列中的每个键,保留一个散列,将第二列中的值添加到该散列中。在文件末尾打印散列键及其值的列表。它可以在一行中完成,但这会混淆算法。

于 2012-06-08T01:44:17.233 回答