merlijn_u has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to put the result of some queries in one big ash.

The data looks like this:

NR------E-mail----------Comment---------Dates-------------Age--Action_ +date 12------Tom@info.com----blablabla-------AM0,PM0,AM1,PM1---32---10-10-2 +001 13------Frank@info.com--blablabla-------AM0,PM0-----------45---10-10-2 +001 14------Sand@info.com---blablabla-------AM1,PM1,PM2-------47---10-10-2 +001 14------Sand@info.com---blablabla-------AM1,PM1,PM2-------47---12-10-2 +001

I was thinking of one hash, key would be NR. Value should be again an hash where E-mail,comment,age,dates are again keys with there actual value. The value of Dates would be again a hash were the keys to it would be the Action Date (see two times NR 14)

so %Arec{NR->%{E-mail->value,comment->value,age->value,dates->%{date1->date1,date2->date2,....}}}

I've managed to code this in my fetch loop:

while (my $c = $st->fetchrow_hashref) { my %analyst_record; $a_record{$c->{ANA_ID}}{e_mail}=$c->{EMAIL}}; $a_record{$c->{ANA_ID}}{Dates}{comment}=$c->{DETAIL}; $a_record{$c->{ANA_ID}}{Dates}{$c->{ACTION_DATE}}{$c->{AM_0}}=$c->{AM_ +0}; $a_record{$c->{ANA_ID}}{Dates}{$c->{ACTION_DATE}}{$c->{AM_1}}=$c->{AM_ +1}; $a_record{$c->{ANA_ID}}{Dates}{$c->{ACTION_DATE}}{$c->{AM_2}}=$c->{AM_ +2}; $a_record{$c->{ANA_ID}}{Dates}{$c->{ACTION_DATE}}{$c->{AM_3}}=$c->{AM_ +3}; $a_record{$c->{ANA_ID}}{Dates}{$c->{ACTION_DATE}}{$c->{AM_4}}=$c->{AM_ +4};

1)Is this the correct way to build my hash?( hashes in hashes?)
2)I want to call a subroutine with as parameter a reference to my NR hash, meaning I don't want to give the funtion not the reference of the Big hash.

I want for every NR to call that subroutine with only one parameter, the reference of the hash of THAT NR.

My current (not working) code:

Show_analyst_row(\$analyst_record{$c->{ANA_ID}}); sub Show_analyst_row { my(%analyst_record) = %{@_}; print "$analyst_record{e_mail}\n"; }

This doesn't Work. How can you give the reference of an hash (this hash is actually the value in another hash) to a subroutine and how do you have to receive that reference-work with in the subroutine?

kind regards
Merlij

(Ps: many thanks to those who can help me, as you see at my question I'm a newbie into Perl. My only resource until now is "Programming Perl" from O'Reilly www.perl.com, do some of you have suggestions of other books should try? Thanks!)

2001-08-18 Edit by Corion : Added formatting, removed CODE tags around whole post.

Replies are listed 'Best First'.
Re: References for subroutines to Hashes in Hashes :)
by mikfire (Deacon) on Aug 17, 2001 at 17:48 UTC
    You are very close. The trick to remember is that hashes and arrays can only store scalars. Perl can have complex data structures only because a reference is a scalar.

    This means that your hash of hashes is really a hash of references to hashes. To pass the reference to a subroutine, then, you need only access the value. In this case simple remove the preceding slash ( sorry, I would try to use a code tag, but I am using Opera and it makes a real mess of things ).

    Hth,
    mikfire

      thanks alot mikfire,
      so the build up of the ashes is correct, woot thats super...

      I'll go try that right know in my code!
      Merlijn

Re: References for subroutines to Hashes in Hashes :)
by suaveant (Parson) on Aug 17, 2001 at 17:56 UTC
    Here is some code that does what you want... I think...
    my %big_ash; my @keys; while(<DATA>) { my @fields = split /--+/, $_; next unless @fields; if($. == 1) { #first line @keys = @fields; next; } my %nr; @nr{@keys} = @fields; $big_ash{$nr{NR}} = \%nr; } print "$big_ash{14}{Dates}\n"; __DATA__ NR------E-mail----------Comment---------Dates-------------Age--Action_ +date 12------Tom@info.com----blablabla-------AM0,PM0,AM1,PM1---32---10-10-2 +001 13------Frank@info.com--blablabla-------AM0,PM0-----------45---10-10-2 +001 14------Sand@info.com---blablabla-------AM1,PM1,PM2-------47---10-10-2 +001 14------Sand@info.com---blablabla-------AM1,PM1,PM2-------47---12-10-2 +001
    this assumes you always have at least -- as a record separator... you may want to use spaces to pad your data and look into unpack to get your data back... or change your delimiter to something like | that you don't have in any of your data...
    Since a hash within a hash is stored as a reference, you do not need the \$analyst_record{$c->{ANA_ID} ... $analyst_record{$c->{ANA_ID} itself will return a ref.

    Update
    Sorry, I missed that you wanted to break up dates... for that add

    $nr{Dates} = [split ',', $nr{Dates};
    after the @nr{@keys} = @fields; line... that will put them in an array so $big_ash{13}{Dates}[0] will give you AM0
    Also... using NR as a key won't work right if you have the same NR twice... which you seem to have, but is the exact same line...

                    - Ant
                    - Some of my best work - Fish Dinner

      damn thats great work of you...

      but no troubles with the -----

      I just putted it that way to give you a vision of the normalisation of my Query. I get my data from Oracle 8, so I just name th collumns....

      but my mayor question about the reference seems awsered so that should bring me further. Is my subroutine correct written, will be able to receive that reference and work with it?

      Much thanks
      Merlijn

        ahh yes, I'd missed the database calls...
        What are the fields your database returns? Your hash does look ok, but I would probably put the AM0 AM1 etc in an array, not a hash... something like...
        for $key (keys %$c) { next unless $key =~ /^[AP]M_\d+$/; push @{$a_record{$c->{ANA_ID}}{Dates}{$c->{ACTION_DATE}}}, $c->{$key} if $c->{$key}; }
        Not tested, but should work... that should go through the keys, matching any that start with AM or PM with an _ and the a number, and push them into an anonymous array if they have a value... this is assuming AM_0 AM_1 etc just hold a 1 or 0 for a yes or no... }

                        - Ant
                        - Some of my best work - Fish Dinner