Adding values to anon hash of hash while looping...

A

adamomitcheney

Hi all,

I'm trying to write a program that loops through a file, extracts time,
date and data from each line then adds the data to a hash, keyed on
time, a reference to which is stored in another hash, keyed on date.

My first attempt looked something like this:
########################################
my $cclicusagebydate;

foreach my $line (@slurpedfile)
{
$line =~ m%(.+?),(.+?),(.+?)%;
my $date = $1;
my $time = $2;
my $cc = $3;

$cclicusagebydate = {$date =>{$time => $cc}};
}

This, of course, failed because I was allocating a new reference with
each iteration of the loop... If I replace the '$cclicusagebydate ='
line with:
$cclicusagebydate->{$date}->{$time} = $cc;
it fails again because I haven't declared $cclicusagebydate as a
hash...

As I see it, there are two options:
1 - put in a line like:
$cclicusagebydate = {'blah' => {'blah' => 'blah'}};
before the foreach loop to define the reference(s), or
2 - put the following into the foreach loop:
$cclicusagebydate = {$date =>{$time => $cc}} unless
ref($cclicusagebydate);
$cclicusagebydate->{$date}->{$time} = $cc;

Am I right - are these the (only) two options? Is there a better way to
make it work the way I hope? If not, which of these two is better?

Thanks.

Adam...
 
P

Paul Lalli

I'm trying to write a program that loops through a file, extracts time,
date and data from each line then adds the data to a hash, keyed on
time, a reference to which is stored in another hash, keyed on date.

My first attempt looked something like this:
########################################
my $cclicusagebydate;

foreach my $line (@slurpedfile)

Don't slurp a file. There's no reason to consume that much memory.
Use a while loop:
while (my $line = said:
{
$line =~ m%(.+?),(.+?),(.+?)%;

Did you really mean to restrict the 'data' field to be only one
character long?
my $date = $1;
my $time = $2;
my $cc = $3;

In general, you shouldn't be using these variables without confirming
that the pattern match actually succeeded.
$cclicusagebydate = {$date =>{$time => $cc}};
}

This, of course, failed because I was allocating a new reference with
each iteration of the loop...

Yes. Very good that you successfully debugged that error.

If I replace the '$cclicusagebydate ='
line with:
$cclicusagebydate->{$date}->{$time} = $cc;
it fails again because I haven't declared $cclicusagebydate as a
hash...

Er. No it doesn't. How are you defining "fails"? What error message
do you get, or what results that don't meet your expectations do you
receive?

If you use an undefined scalar variable as a hash-reference, the hash
auto-vivifies.
As I see it, there are two options:
1 - put in a line like:
$cclicusagebydate = {'blah' => {'blah' => 'blah'}};
before the foreach loop to define the reference(s), or
2 - put the following into the foreach loop:
$cclicusagebydate = {$date =>{$time => $cc}} unless
ref($cclicusagebydate);
$cclicusagebydate->{$date}->{$time} = $cc;

Am I right - are these the (only) two options? Is there a better way to
make it work the way I hope? If not, which of these two is better?

I don't see how either of those options would help you. Can you post a
short-but-complete script that demonstrates your problem, along with
error messages you receive?

When I modify your program above to use the second line that you said
"fails" (along with some other stylistic modifications), I get the
following:

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my $cclicusagebydate;

while ( my $line = <DATA>) {
if ($line =~ m%(.+?),(.+?),(.+)%){
my $date = $1;
my $time = $2;
my $cc = $3;
$cclicusagebydate->{$date}->{$time} = $cc;
} else {
warn "$line didn't match the pattern\n";
}
}

print Dumper $cclicusagebydate;

__DATA__
2005-09-02,10:45:02,foo bar baz
2005-11-05,11:22:33,second line

Output:
$VAR1 = {
'2005-11-05' => {
'11:22:33' => 'second line'
},
'2005-09-02' => {
'10:45:02' => 'foo bar baz'
}
};


Paul Lalli
 
X

xhoster

This, of course, failed because I was allocating a new reference with
each iteration of the loop... If I replace the '$cclicusagebydate ='
line with:
$cclicusagebydate->{$date}->{$time} = $cc;
it fails again because I haven't declared $cclicusagebydate as a
hash...

I have no idea what "failed" means in this context. Provide the error
message, or warning message, or some other evidence that something is
actually "failing".

Xho
 
A

adamomitcheney

Paul Lalli wrote:
-8 said:
Don't slurp a file. There's no reason to consume that much memory.
Use a while loop:


Did you really mean to restrict the 'data' field to be only one
character long?

No, missed the '$' out...
In general, you shouldn't be using these variables without confirming
that the pattern match actually succeeded.


Yes. Very good that you successfully debugged that error.

Oooh, sarcasm. Brilliant. Glad I asked the question now...
If I replace the '$cclicusagebydate ='

Er. No it doesn't. How are you defining "fails"? What error message
do you get, or what results that don't meet your expectations do you
receive?

If you use an undefined scalar variable as a hash-reference, the hash
auto-vivifies.

Aaah, OK. I hadn't realised I needed to declare the hash
%cclicusagebydate and that was confusing me... (In my defense, it's
late on a Friday...)

-8 said:
When I modify your program above to use the second line that you said
"fails" (along with some other stylistic modifications), I get the
following:
Paul Lalli

Thanks Paul.
 
P

Paul Lalli

Oooh, sarcasm. Brilliant. Glad I asked the question now...

There was absolutely no trace of sarcasm when I wrote that. I was
sincerely grateful and congratulatory that you debugged the error you
received. Far too many posters here do not make any attempt at doing
so.

Try counting to 10 before you make such assumptions about those who are
attempting to help you.
Aaah, OK. I hadn't realised I needed to declare the hash
%cclicusagebydate and that was confusing me... (In my defense, it's
late on a Friday...)

Er, no. I never said anything of the sort. No where should you be
declaring a hash named %cclicusagebydate. I said that the code you
posted, modified with the one replacement line you specified, works
as-is.

Please take another look at the code I reposted, and you'll see what
I'm talking about. I used your line
$cclicusagebydate->{$date}->{$time} = $cc; verbatim, and did not
receive any results that would make me say "it failed".

Paul Lalli
 
A

adamomitcheney

Paul said:
There was absolutely no trace of sarcasm when I wrote that. I was
sincerely grateful and congratulatory that you debugged the error you
received. Far too many posters here do not make any attempt at doing
so.

Try counting to 10 before you make such assumptions about those who are
attempting to help you.

My apologies Paul - I did think it was sarcasm, but the response was
intended to be humourous rather than confrontational. Note to self:
maybe it's finally time to start using smileys.
Er, no. I never said anything of the sort. No where should you be
declaring a hash named %cclicusagebydate. I said that the code you
posted, modified with the one replacement line you specified, works
as-is.

Sorry, that was a brain-fart on my part caused by a typo in another bit
of my code that I hadn't cleaned up from when I'd been playing around
trying to get this to work.

Going to go home now. My brain is obviously incapable of even the
simplest things at the moment.
Paul Lalli

Once again, thanks for your help Paul.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top