Algorithm 在Perl中更改键时聚合总计

Algorithm 在Perl中更改键时聚合总计,algorithm,perl,aggregate,pseudocode,Algorithm,Perl,Aggregate,Pseudocode,我有一个输入文件,格式如下 ant,1 bat,1 bat,2 cat,4 cat,1 cat,2 dog,4 我需要为每个键(第1列)聚合col2,因此结果是: ant,1 bat,3 cat,7 dog,4 其他考虑: 假设输入文件已排序 输入文件相当大(大约1M行),所以我不想使用数组并占用内存 每个输入行都应该在读取时进行处理,然后移到下一行 我需要将结果写入一个输出文件 我需要用Perl来实现这一点,但伪代码或算法也同样有用 谢谢 这就是我想到的。。。想看看这是否可以写得更好/优雅

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

ant,1
bat,1
bat,2
cat,4
cat,1
cat,2
dog,4
我需要为每个键(第1列)聚合col2,因此结果是:

ant,1
bat,3
cat,7
dog,4
其他考虑:

  • 假设输入文件已排序
  • 输入文件相当大(大约1M行),所以我不想使用数组并占用内存
  • 每个输入行都应该在读取时进行处理,然后移到下一行
  • 我需要将结果写入一个输出文件
  • 我需要用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";
    }
    
    open infile,outFile
    上一行=;
    打印行=$prev\u行;
    while(){
    当前行=$;
    @prev_cols=拆分(“,”,$prev_行);
    @curr_cols=拆分(“,”,$curr_line);
    如果($prev\u cols[0]相等于$curr\u cols[0]){
    $prev_cols[1]+=curr_cols[1];
    $print_line=“$prev_cols[0],$prev_cols[1]\n”;
    $print_flag=0;
    }
    否则{
    $print outFile“$print_line”;
    $print_flag=1;
    $print\u line=$curr\u line;
    }
    $prev_line=$curr_line;
    }
    如果($print_flag=1){
    打印输出文件“$curr_line”;
    }   
    否则{
    打印输出文件“$print_line”;
    }
    
    这在perl中是微不足道的。在文件输入上循环。以逗号分隔输入行。对于第一列中的每个键,保留一个散列,在第二列中向其中添加值。在文件末尾,打印哈希键及其值的列表。它可以在一行中完成,但这会混淆算法。

    使用Perl的

    • -a
    -n
    -p
    一起使用时,打开自动拆分模式。当
    -n
    -p
    生成
    循环时,隐式
    -split
    @F
    数组执行隐式
    拆分
    命令是隐式
    中的第一件事

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

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

    ant,1 bat,3 cat,7 dog,4 蚂蚁,1 蝙蝠,3 猫,7
    狗,谢谢你。这很有效。然后我们将所有数据加载到内存中(以散列形式)。。。正确的?如果我有一个避免加载到内存中的大文件,该怎么办?这个解决方案非常优雅。我需要学习更多关于Perl哈希的知识。确实,哈希为蚂蚁、蝙蝠、猫和狗各保留一个条目。但是,散列只为蚂蚁保留一个运行总数,为蝙蝠保留一个运行总数,以此类推。它不存储输入的每一行。您的应用程序是否带来了如此多的不同种类的动物,以至于每个动物只运行一个总数是不合理的?是的,唯一密钥的数量将非常大。我不能把每件事都搞砸。对于较小的集合,解决方案会很好地工作。我明白了。你的输入是否保证所有的蚂蚁都会依次出现,然后是所有的蝙蝠,等等。?或者蚂蚁、蝙蝠、猫和狗可能都是交错的吗?我将对输入文件进行排序(使用unix排序),这样就保证了顺序。谢谢Greg。但我的限制是,我的输入文件将是巨大的,我不想使用散列,因为将有太多的唯一键。所以,我需要处理每一行,因为它进来。。。i、 e,如果下一个键不同,则打印它;如果下一个键相同,则将其聚合。请评论我的代码。谢谢
    while (<>) {
      @F = split(' ');
      print pop(@F), "\n";
    }
    
    $ perl -F, -lane '$s{$F[0]} += $F[1];
        END { print "$_,$s{$_}" for sort keys %s }' input
    
    ant,1 bat,3 cat,7 dog,4