代码之家  ›  专栏  ›  技术社区  ›  joe

如何自动增加Perl哈希值?

  •  -2
  • joe  · 技术社区  · 15 年前

    数据库数据:

    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基于银行。

    用0,1,2,3,4填写信用证ID(我需要填写这个)

    我试着像这样自动化

     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 回复  |  直到 15 年前
        1
  •  5
  •   Hynek -Pichi- Vychodil Paulo Suassuna    15 年前

    很简单,您应该保存与索引分开的自动增量。

    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
    
        2
  •  1
  •   Hobo    15 年前

    我想你的问题是

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

    在密钥中包含声明-您需要将计数器保持在护照和银行级别(可能在单独的变量中)。

        3
  •  1
  •   Jonathan Leffler    15 年前

    当您第一次看到护照号、银行号和对账单号的新组合时,您不想将变量设置为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
    

    使用Perl5.10.0和SnowLeopard(Macosx10.6.1)的分布,我得到:

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

    这显然非常接近您作为测试用例所拥有的。

    现在,您还没有清楚地解释您对输出的关注。AFAICS,你得到的和你想要的之间唯一的区别就是在一些值周围没有引号。

    我认为你应该采取懒惰和傲慢的珠光组合。显然,带引号的数字和不带引号的数字之间存在一些差异,但是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'时,您传递一个对散列的引用,转储程序会识别这一点,并将其作为要分析的单个值处理。