我有一个csv文件transcation.csv
,如下所示:
TransactionID,Date,AccNum,Type,Amt
657520,02-07-1999,016901581432,Debit,16000
657524,02-07-1999,016901581432,Debit,13000
657538,09-07-1999,016901581432,Credit,11000
657548,18-07-1999,016901581432,Credit,15500
657519,02-07-1999,016901581433,Debit,12000
657523,02-07-1999,016901581433,Credit,11000
657529,03-07-1999,016901581433,Debit,15000
657539,10-07-1999,016901581433,Credit,10000
657541,11-07-1999,016901581434,Debit,12000
657525,03-07-1999,016901581434,Debit,15000
657533,05-07-1999,016901581434,Credit,12500
我应该从transaction.csv
读取数据并将其存储在哈希中。然后将哈希和帐号列表传递给函数,然后使用散列中的数据计算所列帐户的总借记金额和贷方金额。
这是我的代码:
#!/usr/bin/perl
my %banks;
&arrhas_banks(\%banks);
my @accnum = qw(016901581432 016901581434);
hasarr_banks(\%banks,\@accnum);
sub arrhas_banks
{
my $banks = shift;
open(FH,"<transaction.csv") or die "Could not open 'transaction.csv' $!\n";
while (my $data=<FH>)
{
chomp($data);
my @records = split ",", $data;
$banks->{$records[0]} =
{ 'AccNum' => $records[2], 'Type' => $records[3], 'Amt' => $records[4] };
}
close(FH);
}
sub hasarr_banks {
my ($banks, $accnum) = @_;
foreach my $id (keys %{$banks}) {
my $answer;
foreach my $num (@{$accnum}) {
if($banks->{$id}{'AccNum'} == $num) {
$answer = 1;
}
}
if($answer) {
my $type = $banks->{$id}{'Type'};
$total{$accnum}{$type} += $banks->{$id}{'Amt'};
}
}
foreach my $no (@{$accnum}} {
print "Debit amount of $no is $total{$accnum}{'Debit'}";
print "Credit amount of $no is $tot{$accnum}{'Credit'}";
}
}
我应该产生这样的输出:
Debit amount of 016901581432 is 29000
Credit amount of 016901581432 is 26500
Debit amount of 016901581434 is 27000
Credit amount of 016901581434 is 12500
但我得到这样的输出:
Debit amount of 016901581432 is 56000
Credit amount of 016901581432 is 39000
Debit amount of 016901581434 is 56000
Credit amount of 016901581434 is 39000
我做错了什么?
#!/usr/bin/perl
my %banks;
&arrhas_banks(\%banks);
my @accnum = qw(016901581432 016901581434);
hasarr_banks(\%banks,\@accnum);
sub arrhas_banks
{
my $banks = shift;
open(FH,"<transaction.csv") or die "Could not open 'transaction.csv' $!\n";
while (my $data=<FH>)
{
chomp($data);
my @records = split ",", $data;
$banks->{$records[0]} =
{ 'AccNum' => $records[2], 'Type' => $records[3], 'Amt' => $records[4] };
}
close(FH);
}
sub hasarr_banks {
my ($banks, $accnum) = @_;
foreach my $id (keys %{$banks}) {
my $answer;
foreach my $num (@{$accnum}) {
if($banks->{$id}{'AccNum'} == $num) {
$answer = 1;
}
}
if($answer) {
my $type = $banks->{$id}{'Type'};
$total{ $banks->{$id}{'AccNum'} }->{$type} += $banks->{$id}{'Amt'};
}
}
foreach my $no (@{$accnum}) {
print "Debit amount of $no is $total{$accnum}{'Debit'}";
print "Credit amount of $no is $total{$accnum}{'Credit'}";
}
}
还没有输出。还是错了?
答案 0 :(得分:3)
您应该尝试使用csv模块,例如Text::CSV
。请注意,在下面的示例中,DATA
文件句柄可以替换为任何IO输入句柄。
use strict;
use warnings;
use Text::CSV;
use feature 'say';
my $c = Text::CSV->new( ); # default settings are ok
$c->column_names( $c->getline(*DATA) ); # set headers
my %acc;
while (my $row = $c->getline_hr(*DATA)) { # $row is a hash ref
if ($row->{Type} eq "Debit") {
$acc{ $row->{AccNum} }{Debit} += $row->{Amt};
} elsif ($row->{Type} eq "Credit") {
$acc{ $row->{AccNum} }{Credit} += $row->{Amt};
} else { warn "Bad csv line '@$row'" } # precaution
}
for my $acc (keys %acc) {
say "Debit amount of $acc is ", $acc{$acc}{Debit};
say "Credit amount of $acc is ", $acc{$acc}{Credit};
}
__DATA__
TransactionID,Date,AccNum,Type,Amt
657520,02-07-1999,016901581432,Debit,16000
657524,02-07-1999,016901581432,Debit,13000
657538,09-07-1999,016901581432,Credit,11000
657548,18-07-1999,016901581432,Credit,15500
657519,02-07-1999,016901581433,Debit,12000
657523,02-07-1999,016901581433,Credit,11000
657529,03-07-1999,016901581433,Debit,15000
657539,10-07-1999,016901581433,Credit,10000
657541,11-07-1999,016901581434,Debit,12000
657525,03-07-1999,016901581434,Debit,15000
657533,05-07-1999,016901581434,Credit,12500
<强>输出:强>
Debit amount of 016901581433 is 27000
Credit amount of 016901581433 is 21000
Debit amount of 016901581434 is 27000
Credit amount of 016901581434 is 12500
Debit amount of 016901581432 is 29000
Credit amount of 016901581432 is 26500
答案 1 :(得分:1)
你是重复计算。
此代码分为两个部分:
首先,由于您的样本数据中的AccNum始终是$accnum
列表中的2个帐户之一,因此$ answer总是为1。
foreach my $ num(@ {$ accnum}){ if($ banks-&gt; {$ id} {'AccNum'} == $ num){ $ answer = 1; } }
其次,您要根据$total
键分配给$accnum
- 但是,$accnum
是对帐户列表的数组引用#s - 看看你的子程序调用。
换句话说,您的$total
hashref只有一个密钥,看起来像“ARRAY(SOMETHING)”而不是每个帐户#的2个密钥。
您需要做的只是分配到正确的帐户#:
if ($answer) {
my $type = $banks->{$id}{'Type'};
$total{ $banks->{$id}{'AccNum'} }->{$type} += $banks->{$id}{'Amt'};
}
另外,就可读性而言,您的代码风格并不是很好。不是我见过的最糟糕的,但绝对不是理想的。