Creating hash with an array as value

Discussion in 'Perl Misc' started by Anders Christensen, Apr 21, 2004.

  1. 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
    Anders Christensen, Apr 21, 2004
    #1
    1. Advertising

  2. On Wed, 21 Apr 2004 16:02:30 +0200, Anders Christensen wrote:

    > 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:
    James Willmore, Apr 21, 2004
    #2
    1. Advertising

  3. Anders Christensen

    Paul Lalli Guest

    On Wed, 21 Apr 2004, Anders Christensen wrote:

    > 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
    Paul Lalli, Apr 21, 2004
    #3
  4. Anders Christensen

    Vetle Roeim Guest

    * 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.

    [...]

    --
    #!/usr/bin/vr
    Vetle Roeim, Apr 21, 2004
    #4
  5. Anders Christensen <> wrote in
    news:c65uri$u2k$:

    > 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.
    Eric J. Roode, Apr 21, 2004
    #5
  6. SOLVED: Creating hash with an array as value

    Thanx for the answers, my issue is now solved:)

    ../Anders
    Anders Christensen, Apr 23, 2004
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. rp
    Replies:
    1
    Views:
    499
    red floyd
    Nov 10, 2011
  2. Une bévue
    Replies:
    5
    Views:
    141
    Une bévue
    Aug 10, 2006
  3. Anthony Martinez
    Replies:
    4
    Views:
    260
    Robert Klemme
    Jun 11, 2007
  4. Michal Suchanek
    Replies:
    6
    Views:
    217
    Nobuyoshi Nakada
    Jun 13, 2007
  5. Srijayanth Sridhar
    Replies:
    19
    Views:
    598
    David A. Black
    Jul 2, 2008
Loading...

Share This Page