简体   繁体   English

关于散列和数组引用的Perl

[英]Perl on Hash and Array References

I have a csv file, transcation.csv , which looks like this: 我有一个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  

I am supposed to read the data from transaction.csv and store it in a hash. 我应该从transaction.csv读取数据并将其存储在哈希中。 And then pass the hash and list of Account numbers to the function, and then make the function to calculate total Debit Amount and Credit Amount of the listed accounts using the data in the hash. 然后将哈希和帐号列表传递给函数,然后使用散列中的数据使函数计算列出的帐户的总借记金额和贷方金额。

This is my code: 这是我的代码:

#!/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'}";
  }
}

I am supposed to produce output like this: 我应该产生这样的输出:

Debit amount of 016901581432 is 29000  
Credit amount of 016901581432 is 26500  
Debit amount of 016901581434 is 27000  
Credit amount of 016901581434 is 12500    

But I am getting output like this: 但我得到这样的输出:

Debit amount of 016901581432 is 56000    
Credit amount of 016901581432 is 39000  
Debit amount of 016901581434 is 56000  
Credit amount of 016901581434 is 39000  

What am I doing wrong? 我究竟做错了什么?


#!/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'}";
  }
}                      

No output yet. 还没有输出。 Still going wrong? 还是错了?

You should try using a csv module, such as Text::CSV . 您应该尝试使用csv模块,例如Text::CSV Note in the below example that the DATA file handle can be replaced with any IO input handle. 请注意,在下面的示例中, 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  

Output: 输出:

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

You are double counting. 你是重复计算。

This code is broken in 2 places: 此代码分为两个部分:

  1. First, Since your AccNum in your sample data is ALWAYS one of the 2 accounts in $accnum list, $answer will ALWAYS be 1. 首先,由于您的样本数据中的$accnum始终是$accnum列表中的2个帐户之一,因此$ answer将始终为1。

    foreach my $num (@{$accnum}) { if($banks->{$id}{'AccNum'} == $num) { $answer = 1; foreach my $ num(@ {$ accnum}){if($ banks - > {$ id} {'AccNum'} == $ num){$ answer = 1; } } }}

  2. Second, you are assigning to $total based on $accnum key - BUT, $accnum is an array reference to a list of account #s - take a look at your subroutine call. 其次,你根据$accnum键分配$total - 但是, $accnum是对帐户列表的数组引用#s - 看一下你的子程序调用。

    In other words, your $total hashref will ONLY have one key, looking like "ARRAY(SOMETHING)" instead of 2 keys one for each account #. 换句话说,你的$total hashref只有一个键,看起来像“ARRAY(SOMETHING)”而不是每个帐号#的2个键。

What you need to do is simply assign to correct account #: 您需要做的只是分配到正确的帐号#:

if ($answer) {
  my $type = $banks->{$id}{'Type'};
  $total{ $banks->{$id}{'AccNum'} }->{$type} += $banks->{$id}{'Amt'};
}

A an aside, your code style is not very good as far as readability. 另外,就可读性而言,您的代码风格并不是很好。 Not the worst I've seen but definitely not close to ideal. 不是我见过的最糟糕的,但绝对不是理想的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM