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

I'm having some trouble in creating a AoA here is the code:
while(($id,$value) = $select->fetchrow_array ) { push @aoa[$id],$value; }
as you can see, I get the data from a database, what I'm trying to do is to make a array of arrays where each @aoa[$id] is a array of values for that $id.
the data is like this:
id value
1 3
1 2
1 10
2 5
2 6
3 4
.. ...
but a got a compile error:
Type of arg 1 to push must be array (not array slice) at file.pl line +62, near "$aoa;"


what I'm doing wrong here ?

Replies are listed 'Best First'.
Re: array of arrays
by dreadpiratepeter (Priest) on Jun 29, 2009 at 13:06 UTC
    the syntax is wrong, what you need is
    push @{$aod[$id]},$value;
    @aod[$id] would be a 1 element array slice.
    with @{$aod[$id]} you are saying that the scalar in position $id in your outer array, is to be used as a reference to an array. Since push needs to be passed an array, not a reference, you use the dereferencing syntax @{} to give it what it needs.
    The first time you push on a particular element the nested array gets auto-vivified, that is automatically created when needed.


    -pete
    "Worry is like a rocking chair. It gives you something to do, but it doesn't get you anywhere."
Re: array of arrays
by davorg (Chancellor) on Jun 29, 2009 at 13:29 UTC

    I recommend the Perl data structures cookbook as a good way to learn about building complex data structures in Perl.

    You've had a couple of explanations of the problems in your code. I wanted to mention something a bit deeper. You're creating an array where the indexes are the ids from your database. Unless your ids are small integers, then you're going to create a very sparse array (i.e. one with a lot of missing values that still take up memory). It might make more sense to consider a hash instead of an array.

    --

    See the Copyright notice on my home node.

    Perl training courses

Re: array of arrays
by jethro (Monsignor) on Jun 29, 2009 at 13:09 UTC
    push @{$aoa[$id]}, ...

    This basically takes the value $aoa[$id] and then looks at the array pointed to by it (indicated with the surrounding @{})

Re: array of arrays
by Marshall (Canon) on Jun 29, 2009 at 13:28 UTC
    It sounds to me like you need a different data structure, a HoA (Hash of Array). This is a hash key that is associated with a list of many key values. This is a more "natural" (meaning more Perl way) for what you are doing.
    #!/usr/bin/perl -w use strict; my %hash; while (<DATA>) { my($id,$value)=split; push @{$hash{$id}}, $value; } foreach my $id (sort{$a<=>$b} keys (%hash)) { print "id=$id values=@{$hash{$id}}\n"; } #prints: #id=1 values=3 2 10 #id=2 values=5 6 #id=3 values=4 __DATA__ 1 3 1 2 1 10 2 5 2 6 3 4
    The "tricky" syntax part is that "extra {}" in @{$hash{$id}} is necessary when using a sub sub-scripted variable (ie just @$hash{$id} won't work! The extra {} tells @ what to operate upon.

    I don't know if this is some sort of homework problem?

      Marshall,
      This is a more "natural" (meaning more Perl way) for what you are doing.

      Would you mind explaining that. The two primary reasons you would use a hash here are if the indexes were not numerical or sparsely populated and you wanted to conserve space. Those 'ifs' are assumptions not supported (or refuted) by facts presented by the OP. While I agree that chances are it is a better fit for this data, making such statements to a (presumably) newbie without explanation can lead to cargo culting.

      Cheers - L~R

        Hi L~R!

        I don't know what "cargo culting" means. I asked about a homework assignment because this problem didn't seem "real-world" to me. Your points about non-numeric, etc are well taken.

        One thing that newbies often miss is the power of Perl list processing. Most of the common languages iterate over some array with an index variable array[$i]. In Perl the way is to iterate over all elements and the index doesn't matter. There is a lot of literature about "off-by-one" errors. Processing a Perl list avoids this problem - there is no "index" variable. It becomes: for everything in this list, do "X".

        I would go as far as to say that as one's experience in Perl increases, the use of [$i] decreases. Now of course there are very valid reasons to use this type of statement! But in general a new Perl'er will overuse this. The use of the Perl hash is also often underused.

Re: array of arrays
by arc_of_descent (Hermit) on Jun 29, 2009 at 13:26 UTC

    Make sure you read the perllol documentation.

Re: array of arrays
by Anonymous Monk on Jun 29, 2009 at 13:28 UTC
    nice, thanks.

    also, to access the inner arrays I use @{} too ? like
    @tmp = @{$aoa[$id]}; print tmp[0];