Reputation: 4181
Working on converting an array to another array. In PHP, this is easy, but Perl has some syntax that I am having a hard time getting my head around and understanding.
Here is my loop in Perl:
foreach my $r (@toindex){
#print Dumper $r;
%indexed{@$r[0]}{'image_id'} = @$r[0]; #Broken
%indexed{"@$r[0]"}{'image_id'} = @$r[0]; #Broken
}
Here is my @toindex array
$VAR1 = [
[
3638584,
'Aperture',
'F13'
],
[
3638588,
'Exposure Bias',
'0 EV'
],
[
3638588,
'Focal Length',
'80.0 mm'
],
];
And here is what I want to do, but in PHP
foreach($indexrows as $k => $v){
$indexed[$v['image_id']]['image_id'] = $v['image_id'];
}
It seems so very simple in PHP, but moving it to Perl is proving to be quite a challenge for me.
Update
Thanks to the help of Sinan Ünür and DVK with that final little pointer, I have a working solution. I'm posting the complete script in case anyone might find some part of it useful in the future.
#!/usr/bin/perl
use strict; use warnings; use DBI; use Data::Dumper;
my $dbh = DBI->connect('dbi:Pg:dbname=database;host=serveraddress','user','password') or die;
my $sth;
my $sql = "SELECT id, field, data FROM table";
my $offset = 0;
my $increment = 20;
my $toindex;
# This loop here is to solve a problem that was not part of the
# original question. I included it to illustrate the syntax for
# looping a database query
do{
$sth = $dbh->prepare($sql . " LIMIT " . $increment . " OFFSET " . $offset);
$sth->execute or die;
$toindex = $sth->fetchall_arrayref;
$offset = $offset + $increment;
}while(@$toindex == 0);
# Alternately, if you do not need a loop below is all you need
# $sth = $dbh->prepare($sql);
# $sth->execute or die;
# $toindex = $sth->fetchall_arrayref;
my %indexed;
foreach my $r ( @$toindex ) {
#print Dumper $r;
my ($id, $field, $value) = @$r;
@{ $indexed{ $id } }{('image_id', $field)} = ($id, $value);
}
print Dumper %indexed;
$dbh->disconnect;
Upvotes: 2
Views: 331
Reputation: 118128
I am going to speculate that you are trying to convert that information to a hash table indexed by the image identifier:
#!/usr/bin/perl
use strict; use warnings;
my $table = [
[ 3638584 => 'Aperture', 'F13' ],
[ 3638588 => 'Exposure Bias', '0 EV' ],
[ 3638588 => 'Focal Length', '80.0 mm' ],
];
my %indexed;
for my $r ( @$table ) {
@{ $indexed{ $r->[0] } }{('image_id', $r->[1])} = @$r[0,2];
}
use YAML;
print Dump \%indexed;
Output:
E:\Home> t --- 3638584: Aperture: F13 image_id: 3638584 3638588: Exposure Bias: 0 EV Focal Length: 80.0 mm image_id: 3638588
You can write the for
loop above less cryptically as:
for my $r ( @$table ) {
my ($id, $field, $value) = @$r;
@{ $indexed{ $id } }{('image_id', $field)} = ($id, $value);
}
which might save a lot of headaches a week from now.
See also the Perl Data Structures Cookbook. Perl comes with excellent documentation; use it.
Upvotes: 3
Reputation: 118128
This does not directly answer the question, but it is useful for learning purposes so I am making it CW.
foreach my $r (@toindex){ #print Dumper $r; %indexed{@$r[0]}{'image_id'} = @$r[0]; #Broken %indexed{"@$r[0]"}{'image_id'} = @$r[0]; #Broken }
In Perl 5 and earlier, you address an individual element of a hash %hash
using the syntax $hash{key}
because the element is a scalar.
Hash keys are always stringified. So, used as key to a hash, @$r[0]
and "@$r[0]"
are identical.
Given a reference to an array $r
, there are two ways of accessing its first element. @$r[0]
is not wrong, but adding sigils to the front gets tedious after a while. Therefore, I found $r->[0]
preferable especially if $r->[0]
contains a reference to a nested data structure (not the case here) so I can write $r->[0]{this}[1]{that}
.
Upvotes: 3