Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

multidimensional array's

by emgi (Initiate)
on Dec 27, 2012 at 18:12 UTC ( #1010560=perlquestion: print w/replies, xml ) Need Help??
emgi has asked for the wisdom of the Perl Monks concerning the following question:

As a very humble and fresh monk I come here to seek some guidance on accomplishing the following: My current project aims to aid in ebookmanagement. It does a lookup in an SQLite database for e-books matching the search criteria. The next step is where I'm stuck right now. The results from the database search need to be returned to the program. An array seems the most obvious solution and while the results consist of a set of columns, it should be a multidimensional one where @results[0] 0-7 holds the first entry, @results1 0-7 the next one and so on. However, due to my poor skills on array's I am unable to put the results into such an array. For a start I tried to put the book's title into elementx 1 of the array but no luck.

$sth = $dbh->prepare("select author, title, language, format, filename +, fullpath, category, tags from ebooks where author like'%$searchauth +%' and title like'%$searchtitle%' and language='$searchlang' and form +at='$searchfmt' and category like'%$searchcategory%' and tags like'%$ +searchtags%' LIMIT 50;");<br/>
(Above is the working query, just for informational purposes.)
Below is my code which can certainly be improved. Please guide me!
$sth->execute(); $loopcount = 0; while ($row = $sth->fetchrow_arrayref()) { # print "@$row[0] @$row[1] @$row[2] @$row[3] \n"; print "File found: @$row[4] \n"; # print "Category: @$row[6] Tags: @$row[7]\n\n"; $author = @$row[0]; $title = @$row[1]; $results[$loopcount] [1] = (@$row[1]); THIS LINE IS NOT WORKING. $language = @$row[2]; $format = @$row[3]; $filename = @$row[4]; $fullpath = @$row[5]; $category = @$row[6]; $tags = @$row[7]; print "$loopcount $results[$loopcount] [1]"; $loopcount++; }
When removing the # from the lines containing the print statements, the output is what you would expect; i.e. results are being returned from the query. My problem is how to put them into the array. I do use 'strict' and the program returns no syntax errors. /emgi

Replies are listed 'Best First'.
Re: multidimensional array's
by 2teez (Priest) on Dec 27, 2012 at 19:48 UTC

    "..$results[$loopcount] [1] = (@$row[1]); THIS LINE IS NOT WORKING..."

    If I get your question right, and you suppose to generate an ARRAY of ARRAY, you could do something like this: Please note, this will only show you how to go about solving your question

    my @AoA; while (<DATA>) { push @AoA, [split]; } use Data::Dump; dd \@AoA; __DATA__ First line of the file. Second line of the file. Third line of the file. Fourth line of the file. Fifth line of the file. Sixth line of the file.
    [ ["First", "line", "of", "the", "file."], ["Second", "line", "of", "the", "file."], ["Third", "line", "of", "the", "file."], ["Fourth", "line", "of", "the", "file."], ["Fifth", "line", "of", "the", "file."], ["Sixth", "line", "of", "the", "file."], ]
    Learn about this and more, please check perldsc and ARRAY of ARRAY

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
Re: multidimensional array's
by NetWallah (Canon) on Dec 27, 2012 at 23:40 UTC
    fetchall_arrayref will return what you say you want to accomplish - a single call that returns a multi-dimensional array. You will not need the "while" loop, unless you want to iterate the array, in which case, a "for" loop is more appropriate.

    Here is sample code:

    my @allrows = @{ $sth->fetchrow_arrayref() }; # Expand ref, to simplif +y access my $first_author = $allrows[0][0]; my $second_author = $allrows[1][0]; my $first_title = $allrows[0][1];
    Also, access to a scalar element of an array is correctly written as
    $language = $row[2]; # Correct $language = @$row[2]; # wrong (at least in perl ver 5)

                 "By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."           -Confucius

      A little known "feature" of fetchall_arrayref is that it will return an array of hashes if you supply it a hash, and if that hash is empty, it will return all the fields.
      my @allrows = @{ $sth->fetchrow_arrayref({}) }; # Expand ref, to simpl +ify access

      YMMV, but I always find it easier to look at $row{language} than $row[2]. I'm sure there's a mild performance hit, but as long as it's not incredibly slow I'd opt for clarity.

      A Monk aims to give answers to those who have none, and to learn from those who know more.
        Ah - learned something today - thank you.

        I avoid "fetchall_*", because I mostly process a row-at-a-time , and use the clearer syntax of fetchrow_hashref.

        The OP's questions were based on managing arrays, and I did not want to bring hashes and confuse that discussion.

        Thanks, space_monk.

                     "By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."           -Confucius

Re: multidimensional array's
by LanX (Bishop) on Dec 27, 2012 at 20:50 UTC

    I didn't really understand the context but for the following line

    $results[$loopcount] [1] = (@$row[1]); THIS LINE IS NOT WORKING.

    can't work, since you can't assign an @array-list to an array element¹, only scalars (simple or references)

    in your case you have the option between

    $results[$loopcount][1] = $row[1]

    which copies references


    $results[$loopcount][1] = [@$row[1]]

    which creates a new array-reference with elements copied (one-level deep)

    While ignoring the rest of your post I hope this helps! =)

    Cheers Rolf

    ¹) well you won't get an error here, because Perl will take the size of the array in scalar context.

Re: multidimensional array's
by Cristoforo (Curate) on Dec 27, 2012 at 21:26 UTC
    If you are going to address columns by name, (author, title, language, format, etc), you might want to get your database results as an array of hashes. DBI recipes is a good start here.

    The little program I wrote returns all rows as an array of hashes. The text after the __END__ token shows a select * from the command line, (to show the contents of the id_minutes table).

    The text after the sqlite result is the Data::Dumper output of the array of hashes.

    #!/usr/bin/perl use strict; use warnings; use DBI; use Data::Dumper; # my $dbh = DBI->connect("dbi:SQLite:dbname=junk.lite","","", {PrintError => 1}) or die "Can't connect"; my $query = q{SELECT * FROM id_minutes}; my $aref = $dbh->selectall_arrayref($query, { Slice => {} }); $dbh->disconnect or die $dbh->errstr; print Dumper $aref; __END__ C:\Old_Data\perlp>sqlite3 junk.lite SQLite version 3.7.3 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> .mode column sqlite> .width 10 10 10 sqlite> .head on sqlite> select * from id_minutes; id month minutes ---------- ---------- ---------- maclaw796 Oct 6 hturner Oct 53 nnt Oct 3 sqlite> C:\Old_Data\perlp>perl $VAR1 = [ { 'month' => 'Oct', 'minutes' => 6, 'id' => 'maclaw796' }, { 'month' => 'Oct', 'minutes' => 53, 'id' => 'hturner' }, { 'month' => 'Oct', 'minutes' => 3, 'id' => 'nnt' } ]; C:\Old_Data\perlp>
Re: multidimensional array's
by 7stud (Deacon) on Dec 27, 2012 at 21:10 UTC
    use strict; use warnings; use 5.012; my $row1_ref = ['a', 'b', 'c']; my $row2_ref = ['xx', 'yy', 'zz']; my $data; push @$data, $row1_ref; push @$data, $row2_ref; use Data::Dumper; say Dumper($data); --output:-- $VAR1 = [ [ 'a', 'b', 'c' ], [ 'xx', 'yy', 'zz' ] ];
    my( $author, $title, $results ) ; while ( my($lineno, $row_ref) = each @$data) { $author = $row_ref->[0]; $title = $row_ref->[1]; $results->[$lineno]->[1] = $row_ref->[2]; } say Dumper($results); --output:-- $VAR1 = [ [ undef, 'c' ], [ undef, 'zz' ] ];

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1010560]
Approved by 2teez
Front-paged by Lotus1
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2018-01-23 00:00 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (238 votes). Check out past polls.