Perl-在文件中汇总数据

Perl-在文件中汇总数据,perl,file,sum,Perl,File,Sum,从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 Chris您可以将哈希用作: my %hash; while (<DA

从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

Chris

您可以将哈希用作:

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";
}
my%hash;
而(){
咀嚼;
my@tmp=split/\\\124;/#在|
my$value=pop@tmp;#最后一个元素是值
pop@tmp;#弹出不需要的条目
my$key=join'|',@tmp;#加入剩余的元素以形成key
$hash{$key}+=$value;#为该键添加值
}
#打印散列键值。
for(排序键%hash){
打印$.'.|'.$hash{$.}.\n”;
}

假设始终有五列,其中第五列是数字,并且始终希望前三列是键

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";
}
使用警告;
严格使用;
我的%totals\u散列;
而()
{
咀嚼;
我的@cols=split/\\|/;
我的$key=join'|',@cols[0..2];
$totals_hash{$key}+=$cols[4];
}
foreach(排序键%totals\u散列)
{
打印“$”,“$总计”{$},“\n”;
}

假定输入文件的记录在单独的行中

perl -n -e 'chomp;@a=split/\|/;$h{join"|",splice@a,0,3}+=pop@a;END{print map{"$_: $h{$_}\n"}keys%h}' < inputfile
perl-n-e'chomp@a=拆分/\ \ |/$h{连接“|”,splice@a,0,3}+=pop@a;结束{print map{“$\:$h{$\}\n“}键%h}”
排序以将具有相同前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);
$prevKey=”“;
$小计=0;
打开(输入文件“$outFile”);
@排序=排序(@行);
foreach$行(@行){
@零件=分割(/\\\;/g,$line);
$value=pop(@parts);
$value-=0;#强制字符串为数字
$key=$parts[0]。“|”。$parts[1]。“|”。$parts[2];
如果($ne$prevKey){
打印输出文件“$prevKey |$subtotal\n”;
$prevKey=$key;
$小计=0;
}
$subtotal+=$value;
}
关闭(输出文件);
如果对200万进行排序使您的箱子堵塞,那么您可能必须根据组将每条记录放入一个文件中,然后对每个文件进行小计。

1-2-3-4我宣布一场代码大战!!!(好的,一个合理可读的代码已经启动。)

my%总和;
m/([^ |]+\\\\\\\\\[^ |]+\\\\\\\[^ |]+.\\\\\\.(\d+)/和$SUMMS{$1}+=2,而;
打印联接(“\n”,(映射{$\\$sums{$\}}排序键%sums),”;

要对前三列匹配的所有记录的最后一列中的数字求和吗?现在,对于更难的一列,如果有多个列要总结怎么办?如果有多个列,这听起来像是SQL的工作,它是为这类事情设计的。-1。为什么OP必须一次读取整个文件,而它可以一次完成,而不需要全部存储在内存中?对不起。谢谢你对这件事的仁慈。我不是想告诉你,只是回答而已。总的来说,我相信你是个好人,也是个好程序员。:-)我的错,我收回了评论。我将学习如何正确处理文件。谢谢你的更正。:)
my %sums;
m/([^|]+\|[^|]+\|[^|]+).*?\|(\d+)/ and $sums{ $1 } += $2 while <>;
print join( "\n", ( map { "$_|$sums{$_}" } sort keys %sums ), '' );