如何自动增加Perl哈希值?

时间:2009-10-20 11:36:11

标签: perl hash

数据库数据:

Passport_No  Bank      statement_no   Credit_id 

4126897     HSBC       2948608         0
4126897     HSBC       2948609         1   
4126858     HSBC       2948591         0  
4126858     barclays   2948595         0
4126858     barclays   2948596         1
4126858     barclays   2948597         2  

信用ID基于银行。

Credit_id(我需要填写)0,1,2,3,4

我试图像这样自动化

 if ($credit{$passport_no}{$bank}) { 
    $credit{$passport_no}{$bank}->{$statement}++;
 } else { 
        $credit{$passport_no}{$bank}->{$statement} = 0;
 } 

我得到的结果是:

VAR1 = '4126897';
$VAR2 = {
          'HSBC' => {
                        '2948608' => 0,
                        '2948609' => '1'
                      }
        };
$VAR3 = '4126858';
$VAR4 = {
          'HSBC' => {
                           '2948591' => 0
                         },
          'barclays' => {
                               '2948595' => 0,
                               '2948596' => '1',
                               '2948597' => '1'
                             }
        };

但我一直在寻找

VAR1 = '4126897';
$VAR2 = {
          'HSBC' => {
                        '2948608' => 0,
                        '2948609' => 1
                      }
        };
$VAR3 = '4126858';
$VAR4 = {
          'HSBC' => {
                           '2948591' => 0
                         },
          'barclays' => {
                               '2948595' => 0,
                               '2948596' => 1,
                               '2948597' => 2
                             }
        };

如何解决这个问题?

3 个答案:

答案 0 :(得分:5)

非常简单,你应该保存与索引分开的自动增量。

use strict;
use warnings;
use Data::Dumper;

my ( %counts, %credit );
while (<DATA>) {
    my ( $passport_no, $bank, $statement ) = split / /;
    $credit{$passport_no}{$bank}{$statement} = $counts{$passport_no}{$bank}++;
}

print Dumper( \%credit );

__DATA__
4126897 HSBC 2948608 0
4126897 HSBC 2948609 1
4126897 barclays 2948610 0
4126897 barclays 2948611 1
4126897 barclays 2948612 2
4126897 SBI 2948613 0
4126897 SBI 2948614 1
4126897 SBI 2948615 2

答案 1 :(得分:1)

当您第一次看到护照号码,银行和帐单号码的新组合时,您似乎不想将变量设置为1,这似乎很奇怪:

拿你的代码,我用了:

#!/bin/perl -w
use strict;
use Data::Dumper;

my %credit;

while (<>)
{
        my($passport_no,$bank,$statement) = split / /;
        if ($credit{$passport_no}{$bank}) {
                $credit{$passport_no}{$bank}->{$statement}++;
        } else {
                $credit{$passport_no}{$bank}->{$statement} = 0;
        }
}

print Dumper(%credit);

我写了一个数据文件(名为data.file):

4126897 HSBC 2948608 13.23
4126897 HSBC 2948609 23.23
4126897 HSBC 2948609 33.23
4126858 HSBC 2948591 43.23
4126858 Barclays 2948595 53.23
4126858 Barclays 2948596 63.23
4126858 Barclays 2948596 73.23
4126858 Barclays 2948597 83.23
4126858 Barclays 2948597 93.23
4126858 Barclays 2948597 14.23

而且,随着与Snow Leopard(MacOS X 10.6.1)一起发布的Perl 5.10.0,我得到了:

$VAR1 = '4126858';
$VAR2 = {
          'Barclays' => {
                          '2948596' => 2,
                          '2948595' => 0,
                          '2948597' => 3
                        },
          'HSBC' => {
                      '2948591' => 0
                    }
        };
$VAR3 = '4126897';
$VAR4 = {
          'HSBC' => {
                      '2948608' => 0,
                      '2948609' => 2
                    }
        };

这显然与您作为测试案例的内容非常接近。

现在,您还没有清楚地解释您对输出的担忧。 AFAICS,你得到的和你想要的唯一区别是缺少一些值的引用。

我认为你应该采用Perl-ish懒惰和傲慢的组合。显然,引用的数字和未引用的数字之间存在一些差异,但Perl很容易在字符串和数字之间进行转换,而且很少能够发现它是“错误的类型”。

如果存在重大问题,请更清楚地解释问题所在,包括样本数据等。

#!/bin/perl -w
use strict;
use Data::Dumper;

my %credit;

while (<>)
{
        my($passport_no,$bank,$statement) = split / /;
        if (defined $credit{$passport_no}{$bank}{$statement}) {
                $credit{$passport_no}{$bank}{$statement}++;
        } else {
                $credit{$passport_no}{$bank}{$statement} = 1;
        }
}

print Dumper(%credit);

给定与以前相同的数据文件,这会产生:

$VAR1 = '4126858';
$VAR2 = {
          'Barclays' => {
                          '2948596' => 2,
                          '2948595' => 1,
                          '2948597' => 3
                        },
          'HSBC' => {
                      '2948591' => 1
                    }
        };
$VAR3 = '4126897';
$VAR4 = {
          'HSBC' => {
                      '2948608' => 1,
                      '2948609' => 2
                    }
        };

此代码使用数据中包含的金额(第四列):

#!/bin/perl -w
use strict;
use Data::Dumper;

my %credit;

while (<>)
{
        my($passport_no,$bank,$statement,$amount) = split / /;
        $credit{$passport_no}{$bank}{$statement} += $amount
}

print Dumper(%credit);

产生输出:

$VAR1 = '4126858';
$VAR2 = {
          'Barclays' => {
                          '2948596' => '136.46',
                          '2948595' => '53.23',
                          '2948597' => '190.69'
                        },
          'HSBC' => {
                      '2948591' => '43.23'
                    }
        };
$VAR3 = '4126897';
$VAR4 = {
          'HSBC' => {
                      '2948608' => '13.23',
                      '2948609' => '56.46'
                    }
        };

最后,使用Data :: Dumper :: Dumper略有不同:

#!/bin/perl -w
use strict;
use Data::Dumper;

my %credit;

while (<>)
{
        my($passport_no,$bank,$statement,$amount) = split / /;
        $credit{$passport_no}{$bank}{$statement} += $amount
}

print Dumper(\%credit);

这会产生更好的输出:

$VAR1 = {
          '4126858' => {
                         'Barclays' => {
                                         '2948596' => '136.46',
                                         '2948595' => '53.23',
                                         '2948597' => '190.69'
                                       },
                         'HSBC' => {
                                     '2948591' => '43.23'
                                   }
                       },
          '4126897' => {
                         'HSBC' => {
                                     '2948608' => '13.23',
                                     '2948609' => '56.46'
                                   }
                       }
        };

当您传递'%credit'时,Perl会发送一个包含四个值的数组 - 第一个是第一个键,第二个是第一个值(结构化),第三个是第二个键,最后一个是第二个值。当您传递'\%credit'时,您将一个引用传递给哈希,并且Dumper会识别它并将其全部视为要解析的单个值。

答案 2 :(得分:1)

我认为你的问题是

 if ($credit{$passport_no}{$bank}) { 
        $credit{$passport_no}{$bank}->{$statement}++;
 } else { 
        $credit{$passport_no}{$bank}->{$statement} = 0;
 }

包括密钥中的陈述 - 您需要将您的柜台保留在护照和银行级别(可能是单独的变量)。