Perl中的密钥更改时的总计

时间:2012-06-08 01:30:16

标签: algorithm perl aggregate pseudocode

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

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中执行此操作,但伪代码或算法可以帮助一样好
  6. 谢谢!

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

    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";
    }
    

3 个答案:

答案 0 :(得分: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有趣的 autovivification 功能。第一次在输入流中遇到特定动物时,不存在计数,因此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;

答案 1 :(得分:1)

使用Perl的awk mode

  
      
  • -a
  •   
     与-n-p一起使用时,

会启用自动分割模式。对split数组的隐式@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

输出:

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

答案 2 :(得分:0)

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