Re: Search an array ref of array refs
by Fastolfe (Vicar) on Nov 01, 2001 at 07:08 UTC
|
foreach my $row (@{$table}) {
print "columns: ", join(", ", @{$row}), "\n";
}
Re-reading your post, it sounds like you're wanting to do a little more than just iteration. If 'rowid' is just a column, and you plan on doing many of these look-ups, you can approach this two different ways.
If by 'rowid' you mean the order the rows appear in the database (thus the order they're SELECTed out, though I'm not sure this can be relied on), iteration or direct-access (e.g. $table->[$rowid]) is probably OK for you. If you're wanting to truly search, something like this might be what you're after:
my %search_cache;
sub search_for {
my $table = shift;
my $value = shift;
return $search_cache{$value} if exists $search_cache{$value};
foreach my $row (@{$table}) {
if ($row->{column} eq $value) {
return $search_cache{$value} = $row;
}
}
return $search_cache{$value} = undef; # cache failure
}
You can also consider storing just the index into @{$table} instead of the row itself. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
Yes, 'rowId' (actually domainId) is the first column in the table. Lemme expand on what I'm doing. I pull the $table, and then strip the first two columns into a hash, and the first column into a seperate array for the CGI::Form->query->popup_menu method:
my %labels = map { @$_->[0] => @$_->[1] } @$table;
my $values = [map ( $_->[0] , @$table )];
Now I need to be able to say, give me the "row" from $table that has a domainId of, say 1. Then I can use the values from that row to fill textboxes for the selected domainId. The search code is great. I was just wondering if there was a way to do it w/ map to avoid the looping code. :) | [reply] [Watch: Dir/Any] [d/l] [select] |
|
@found = grep { $_->[$column] == $searching_for } @$table;
| [reply] [Watch: Dir/Any] [d/l] |
Re: Search an array ref of array refs
by jeroenes (Priest) on Nov 01, 2001 at 11:47 UTC
|
I personally would follow your first hunch and fetch the row from DBI. Why? Databases are optimized for searching the tables, perl is not. SQL is more clear for searching. Just compare the other solutions with a simple SQL query:
select * from table where id=$rowid;.
Another point, the databases mostly scale very well. If your table exceeds let's say more than 1000 items, perl will seriously slow down.
The performance penalty of the additional DBI call moreover probably is pretty small.
Jeroen
"We are not alone"(FZ) | [reply] [Watch: Dir/Any] [d/l] |
|
Granted, the search is much more efficient in the DB, but I already have the whole table because I just used it to create a SELECT box on my web page. So the whole genesis behind this was to avoid another round trip to the DB, which IMHO, is more costly (but I could be wrong). :)
| [reply] [Watch: Dir/Any] |
|
What are you optimizing than? Execution speedup cq load time?
Are you sure that it takes significantly more time to do an
additional query to the server? I guess the connection is not
closed between the statement. Maybe the DB is on the same box
as the webserver.
And even if it takes some additional timeframe (probably very
small, test it!) for the query, is it worth the worse
maintainability of perl code vs the SQL code?
I generally would answer 'no', but your situation may be
different. As ppl say: only optimize the code that needs
optimization. Optimization leads to less quality code,
so be sure you need it. Just consider what you are doing.
| [reply] [Watch: Dir/Any] |
Re: Search an array ref of array refs
by andye (Curate) on Nov 01, 2001 at 17:55 UTC
|
my $table = $sth->fetchall_hashref('row_id');
print "Row 14 contains $table->{14}{num_bananas} bananas";
http://search.cpan.org/doc/TIMB/DBI-1.20/DBI.pm#fetchall_hashref
andy. | [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] |
|
No probs. fetchall_hashref() is new, so you might need to update your DBI, and maybe DBD, modules.
andy.
| [reply] [Watch: Dir/Any] |
Re: Search an array ref of array refs
by bittondb (Novice) on Nov 01, 2001 at 08:22 UTC
|
my $domain_ip;
map { if($_->[0] == $domainid){ $domain_ip = @$_->[2] } } @$table;
Tx all! :) | [reply] [Watch: Dir/Any] [d/l] |
|
I think grep makes more sense in this case. Assuming you know there is only one result per $id, and don't mind checking the entire datastructure, this should work:
my $domain_ip = (grep {$_->[0] == $domainid} @$table)[0]->[2];
As in the folloing example:
#!/usr/bin/perl -wT
use strict;
my $table = [ [7, 'tigers', 600],
[8, 'elephants', 250],
[9, 'lions', 500], ];
my $id = 8;
my $fieldindex = 1;
my $animal = (grep {$_->[0] == $id} @$table)[0]->[$fieldindex];
print "id=$id fieldindex=$fieldindex => animal=$animal\n";
=OUTPUT
id=8 fieldindex=1 => animal=elephants
-Blake
| [reply] [Watch: Dir/Any] [d/l] [select] |