Creating hash with an array as value

A

Anders Christensen

Hi, I'm selecting two columns from my database. What I want to do with the
fetched data is to organize it into a single hash so that each different A
from the database is used as the hash-key. The hash-value should be an
array containing every B from the database, where A and B is on the same
row. An example:
----------------
| A | B |
----------------
| text1 | foo |
| text2 | bar |
| text1 |foobar |
| text3 | oof |
| text3 | test |
| text1 | rab |
----------------

I want to end up with one hash, where...
$prods->{text1} is the array (foo, foobar, rab)
$prods->{text2} is the array (bar)
$prods->{text3} is the array (oof, test)

I've tried the following code without succes :
my %hack_hash;
my $prods = \%hack_hash;
SendSQL("SELECT A, B FROM table WHERE 1");
while (MoreSQLData()) {
my ($a, $b) = FetchSQLData();
push $prods->{$a}, $b;
}

I receive this error: "Type of arg 1 to push must be array (not hash
element)"

To proof to myself, that it is possible to arrange data as I want, I
executed the following code succesfully - with the desired result. Heres
the "proof-code":

my %hack_hash;
my $prods = \%hack_hash;
my @tmp1 = ('foo', 'foobar', 'rab');
$prods->{'text1'} = \@tmp1;
my @tmp2 = ('bar');
$prods->{'text2'} = \@tmp2;
my @tmp3 = ('oof', 'test');
$prods->{'text3'} = \@tmp3;

Can someone give me a tip? If possible at all, I'd like to do it in one
single loop...

../Anders
 
J

James Willmore

Hi, I'm selecting two columns from my database. What I want to do with the
fetched data is to organize it into a single hash so that each different A
from the database is used as the hash-key. The hash-value should be an
array containing every B from the database, where A and B is on the same
row. [ ... ]
Can someone give me a tip? If possible at all, I'd like to do it in one
single loop...

You might be able to use DBIx::Table2Hash
(http://search.cpan.org/~rsavage/DBIx-Table2Hash-1.12/Table2Hash.pm)

You can read each record from a datasource into a hash reference in a
while loop. This is covered in the DBI documentation.

HTH

--
Jim

Copyright notice: all code written by the author in this post is
released under the GPL. http://www.gnu.org/licenses/gpl.txt
for more information.

a fortune quote ...
Famous last words:
 
P

Paul Lalli

Hi, I'm selecting two columns from my database. What I want to do with the
fetched data is to organize it into a single hash so that each different A
from the database is used as the hash-key. The hash-value should be an
array containing every B from the database, where A and B is on the same
row. An example:
----------------
| A | B |
----------------
| text1 | foo |
| text2 | bar |
| text1 |foobar |
| text3 | oof |
| text3 | test |
| text1 | rab |
----------------

I want to end up with one hash, where...
$prods->{text1} is the array (foo, foobar, rab)
$prods->{text2} is the array (bar)
$prods->{text3} is the array (oof, test)

I've tried the following code without succes :
my %hack_hash;
my $prods = \%hack_hash;
SendSQL("SELECT A, B FROM table WHERE 1");
while (MoreSQLData()) {
my ($a, $b) = FetchSQLData();
push $prods->{$a}, $b;
}

I receive this error: "Type of arg 1 to push must be array (not hash
element)"

You need to tell Perl that $prods->{$a} is an array reference (because at
this point in your code, it's nothing - you need to autovivify it). To
do so, dereference the new reference:

push @{$prods->{$a}}, $b;

That says "Push $b onto the array referenced by the value of the hash
referenced by $prods keyed at $a." If no such array reference exists, it
will spring into existence.

Paul Lalli
 
V

Vetle Roeim

* Anders Christensen
[...]
I want to end up with one hash, where...
$prods->{text1} is the array (foo, foobar, rab)
$prods->{text2} is the array (bar)
$prods->{text3} is the array (oof, test)

I've tried the following code without succes :
my %hack_hash;
my $prods = \%hack_hash;
SendSQL("SELECT A, B FROM table WHERE 1");
while (MoreSQLData()) {
my ($a, $b) = FetchSQLData();
push $prods->{$a}, $b;
}

I receive this error: "Type of arg 1 to push must be array (not hash
element)"

If I'm not mistaken, you'd want to push like this instead:

push @{ $prods->{$a} }, $b;

That should produce the result you want. The trick here is to force
the hash element to be an array reference. :)

Btw; there's no reason to use $prod when you could use %hach_hash
directly like this:

push @{ $hach_hash{$a} }, $b;


HTH.

[...]
 
E

Eric J. Roode

I've tried the following code without succes :
my %hack_hash;
my $prods = \%hack_hash;
SendSQL("SELECT A, B FROM table WHERE 1");
while (MoreSQLData()) {
my ($a, $b) = FetchSQLData();
push $prods->{$a}, $b;
}

I receive this error: "Type of arg 1 to push must be array (not hash
element)"

Yeah, the first argument to push *must* begin with an @ symbol. What you
need is:

push @{ $prods->{$a} }, $b;

Other than that, you're on the right track.
 

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

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top