It seems odd that you don't want to set the variable to 1 when you first see a new combination of passport number, bank and statement number:
Taking your code, I used:
#!/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);
I wrote a data file (called 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
And, with Perl 5.10.0 as distributed with Snow Leopard (MacOS X 10.6.1), I got:
$VAR1 = '4126858';
$VAR2 = {
'Barclays' => {
'2948596' => 2,
'2948595' => 0,
'2948597' => 3
},
'HSBC' => {
'2948591' => 0
}
};
$VAR3 = '4126897';
$VAR4 = {
'HSBC' => {
'2948608' => 0,
'2948609' => 2
}
};
This is clearly very close to what you have as a test case.
Now, you have not clearly explained what concerns you about the output. AFAICS, the only difference between what you got and what you wanted was the absence of some quotes around some of the values.
I think you should adopt a Perl-ish combination of laziness and hubris. Clearly, there are some differences between the quoted numbers and the unquoted numbers, but Perl will convert between strings and numbers very readily, and you will seldom be able to spot that it is the 'wrong type'.
If there is a big issue, please explain more clearly what the problem is, including sample data, etc.
#!/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);
Given the same data file as before, this yields:
$VAR1 = '4126858';
$VAR2 = {
'Barclays' => {
'2948596' => 2,
'2948595' => 1,
'2948597' => 3
},
'HSBC' => {
'2948591' => 1
}
};
$VAR3 = '4126897';
$VAR4 = {
'HSBC' => {
'2948608' => 1,
'2948609' => 2
}
};
And this code, which uses the amount (fourth column) that was included in the data:
#!/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);
Yields the output:
$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'
}
};
And, finally, using Data::Dumper::Dumper slightly differently:
#!/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);
This yields the better output:
$VAR1 = {
'4126858' => {
'Barclays' => {
'2948596' => '136.46',
'2948595' => '53.23',
'2948597' => '190.69'
},
'HSBC' => {
'2948591' => '43.23'
}
},
'4126897' => {
'HSBC' => {
'2948608' => '13.23',
'2948609' => '56.46'
}
}
};
When you pass '%credit', Perl sends an array of four values - the first is the first key, the second is the first value (structured), the third is the second key, and the last is the second value. When you pass '\%credit', you pass a single reference to the hash, and Dumper recognizes this and treats it all as a single value to be dissected.