【问题标题】:Perl - Summarize Data in FilePerl - 汇总文件中的数据
【发布时间】:2011-05-18 16:16:53
【问题描述】:

在 Perl 中有大约 200 万条记录的文件中汇总数据的最佳方法是什么?

例如:这样的文件,

ABC|XYZ|DEF|EGH|100

ABC|XYZ|DEF|FGH|200

SDF|GHT|WWW|RTY|1000

SDF|GHT|WWW|TYU|2000

前3栏需要这样总结,

ABC|XYZ|DEF|300

SDF|GHT|WWW|3000

克里斯

【问题讨论】:

  • 您想对前三列匹配的所有记录的最后一列的数字求和?

标签: perl file sum


【解决方案1】:

您可以将哈希用作:

my %hash;
while (<DATA>) {
        chomp;
        my @tmp = split/\|/;     # split each line on |
        my $value = pop @tmp;    # last ele is the value
        pop @tmp;                # pop unwanted entry
        my $key = join '|',@tmp; # join the remaining ele to form key

        $hash{$key} += $value;   # add value for this key
}

# print hash key-values.
for(sort keys %hash) {
        print $_ . '|'.$hash{$_}."\n";
}

Ideone link

【讨论】:

  • 现在来点强硬的,
  • 如果要汇总的列不止一列怎么办?
  • 如果有多个列,这听起来像是 SQL 的工作,它是为这类事情而设计的。
【解决方案2】:

假设总是有五列,其中第五列是数字,并且您总是希望前三列作为键...

use warnings;
use strict;

my %totals_hash;

while (<>)
{
  chomp;
  my @cols = split /\|/;

  my $key = join '|', @cols[0..2];

  $totals_hash{$key} += $cols[4];
}

foreach (sort keys %totals_hash)
{
  print $_, '|', $totals_hash{$_}, "\n";
}

【讨论】:

    【解决方案3】:

    假设您的输入文件的记录位于不同的行中。

    perl -n -e 'chomp;@a=split/\|/;$h{join"|",splice@a,0,3}+=pop@a;END{print map{"$_: $h{$_}\n"}keys%h}' < inputfile
    

    【讨论】:

      【解决方案4】:

      排序以将具有相同前 3 个三元组的所有记录彼此相邻放置。当出现一组不同的三元组时,迭代并剔除一个小计。

      $prevKey="";
      $subtotal=0;
      open(INPUTFILE, "<$inFile");
      @lines=<INPUTFILE>;
      close (INPUTFILE);
      open(OUTFILE, ">$outFile");
      @sorted=sort(@lines);
      foreach $line(@lines){
          @parts=split(/\|/g, $line);
          $value=pop(@parts);
          $value-=0; #coerce string to a number
          $key=$parts[0]."|".$parts[1]."|".$parts[2];
          if($key ne $prevKey){
              print OUTFILE "$prevKey|$subtotal\n";
              $prevKey=$key;
              $subtotal=0;
              }
          $subtotal+=$value;
          }
      close(OUTFILE);
      

      如果对 200 万条数据进行排序会阻塞您的盒子,那么您可能必须根据组将每条记录放入一个文件中,然后对每个文件进行小计。

      【讨论】:

      • -1。为什么要强制 OP 一次读取整个文件,而无需将整个文件都放在内存中?
      • 对不起。感谢您对此表示慈善。我不是要骗你,只是回答。我敢肯定,你是一个好人,一个好的程序员。 :-)
      • 我的错,我收回评论。我将学习如何正确处理文件。感谢您的更正。 :)
      【解决方案5】:

      1-2-3-4 我宣布一场代码高尔夫大战!!!(好吧,一个可读性强代码高尔夫尘埃落定。)

      my %sums;
      m/([^|]+\|[^|]+\|[^|]+).*?\|(\d+)/ and $sums{ $1 } += $2 while <>;
      print join( "\n", ( map { "$_|$sums{$_}" } sort keys %sums ), '' );
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-05
        • 2018-04-23
        • 1970-01-01
        • 2017-01-19
        相关资源
        最近更新 更多