I am trying to build a hash depending on the in a database table that contains a 1 or 0 depending if there is data for a given element.
Given the following input table:
id fname lname 1 Joe Smith 2 Sally Smith
Here is the code I am using:
use DBI;
$dbh = DBI->connect("DBI:CSV:f_dir=./");
$query = "select id, fname, lname";
$sth->prepare($query);
$sth->execute();
while ($rowdata = $sth->fetchrow_hashref) {
$hash{$rowdata->{'id'}} = $rowdata{'id'};
if ($rowdata->{'fname'}) { $hash{$rowdata->{'id'}}{'fname'} = 1; }
if ($rowdata->{'lname'}) { $hash{$rowdata->{'id'}}{'lname'} = 1; }
}
print Dumper(\%hash);
Yet, I do not get the expected results. I get the following:
$VAR1 = {
'' => undef
};
I would expect to see something like the following (constructed my myself and may or may not be valid):
$VAR1 = {
{
'' => 1
'fname' => 'John'
'lname' => 'Smith'
{
{
'' => 2
'fname' => 'Sally'
'lname' => 'Smith'
{
};
Update: Changed all references to $rowdata{} to $rowdata->{}.
That is not exactly what I am looking for. I need to basically create a has with each of the input columns indexed by id that has a 1 or 0 in the field depending on whether the database field is null or if it has data.
That code just facilitates repeated lookup on the database for a given input column.
Thanks for the reply, though.
use strict;!!!
You're doing this in two steps. As a result of the line
$hash{$rowdata->{'id'}} = $rowdata->{'id'};
$hash{$rowdata->{'id'}} has an integer for a value, and you're using that as a symbolic reference to a new hash.
use strict would have prevented you from doing that.
I think you can change the code to do what you want, by changing that line to
$hash{$rowdata->{'id'}} = { '' => $rowdata->{'id'} };
Hmmm... I must admit (if it is not obvious) that there a number of things about hashes that I do not understand.
What do you mean by symbolic reference to a new hash?
I have made the change that you suggested and now I get this:
$VAR1 = {
'' => {
'' => undef
}
};
What I need to be able to do later is to reference the has created like this:
foreach $key (keys %hash) {
print $key, $key{'fname'}, $key{'lname'}, "\n";
}
What do you mean by symbolic reference to a new hash?Well, first of all, you're setting the value of $hash{$id} to, say, 1. And then you set $hash{$id}{'fname'} to "foo". As a result, you really are trying to set $1{'fname'} to "foo".
What I need to be able to do later is to reference the has created like this:
foreach $key (keys %hash) { print $key, $key{'fname'}, $key{'lname'}, "\n"; }
No way, but you will be able to use
foreach $key (keys %hash) {
print $key, $hash{$key}{'fname'}, $hash{$key}{'lname'}, "\n"; }
OK, ok, ok. I think I finally understand, finally.
I had tried that change from earlier and it did not make any difference at that time as I had not accounted for/changed the code to deal with the hashrefs correclty (->). I have now made both changes and it does exactly what I wanted it to.
I have learned much more about hashes than I realized I did not know.
Thanks (and thanks for the patience).
You've used fetchrow_hashref but you're treating the value you get from it as if it were a hash rather than a hashref. Use $rowdata->{id} instead of $rowdata{id}. (Use -> everywhere you mention $rowdata) use strict would have caught this for you.
my %hash = (id => "123", fname => "Fred);
my $hashref = \%hash;
print "$hash{id}\n";
print "$hashref->{id}\n";
$VAR1 = [
{
'id' => 1,
'fname' => 'John',
'lname' => 'Smith',
},
{
'id' => 2,
'fname' => 'Sally',
'lname' => 'Smith',
},
];
Then with your friend [map], you can massage this structure thusly:
my %hash = map { $_->{'id'} => $_ } @$data;
which would result in something along the lines of
$VAR2 = {
'1' => {
'id' => 1,
'fname' => 'John',
'lname' => 'Smith',
},
'2' => {
'id' => 2,
'fname' => 'Sally',
'lname' => 'Smith',
},
};
perlmonks.org content © perlmonks.org and bart, bfdi533, Codon, duff, runrig, zer
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03