首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >哈希和数组引用上的Perl

哈希和数组引用上的Perl
EN

Stack Overflow用户
提问于 2012-09-29 16:39:00
回答 2查看 227关注 0票数 1

我有一个csv文件,transcation.csv,如下所示:

代码语言:javascript
运行
复制
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读取数据并将其存储在散列中。然后将散列和帐号列表传递给函数,然后使用散列中的数据创建函数来计算所列帐户的总借方金额和贷方金额。

这是我的密码:

代码语言:javascript
运行
复制
#!/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'}";
  }
}

我应该生产出这样的产品:

代码语言:javascript
运行
复制
Debit amount of 016901581432 is 29000  
Credit amount of 016901581432 is 26500  
Debit amount of 016901581434 is 27000  
Credit amount of 016901581434 is 12500    

但是我得到了这样的输出:

代码语言:javascript
运行
复制
Debit amount of 016901581432 is 56000    
Credit amount of 016901581432 is 39000  
Debit amount of 016901581434 is 56000  
Credit amount of 016901581434 is 39000  

我做错了什么?

代码语言:javascript
运行
复制
#!/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'}";
  }
}                      

还没有输出。还在出错吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-09-29 16:53:40

你在重复计算。

此代码在以下两个地方被破坏:

  1. 首先,由于示例数据中的AccNum始终是$accnum列表中的两个帐户之一,所以$answer始终为1。 我的$num (@{$accnum}) { if($banks->{$id}{'AccNum'} == $num) { $answer = 1;}
  2. 其次,您将基于$total键分配给$accnum --但是,$accnum是对account #s列表的数组引用--查看您的子例程调用。 换句话说,您的$total散列只有一个键,看起来像“数组(某物)”,而不是每个帐户#的两个键。

您需要做的只是简单地分配到正确的帐户#:

代码语言:javascript
运行
复制
if ($answer) {
  my $type = $banks->{$id}{'Type'};
  $total{ $banks->{$id}{'AccNum'} }->{$type} += $banks->{$id}{'Amt'};
}

顺便说一下,您的代码样式就可读性而言并不是很好。不是我见过的最坏的,但绝对不是理想的。

票数 1
EN

Stack Overflow用户

发布于 2012-09-29 18:32:07

您应该尝试使用csv模块,例如Text::CSV。注意,在下面的示例中,可以用任何IO输入句柄替换DATA文件句柄。

代码语言:javascript
运行
复制
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  

输出:

代码语言:javascript
运行
复制
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
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12654453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档