duan4369
2010-06-18 20:43
浏览 190
已采纳

循环遍历数组以在Perl中构建多维数组,从PHP转换,并在语法上错误

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;
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • dongwei6457 2010-06-18 21:01
    已采纳

    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.

    点赞 打赏 评论
  • drodsh7940 2010-06-18 20:46
    $indexed{ $r->[0] }{'image_id'} = $r->[0];
    
    点赞 打赏 评论
  • dqaq59269 2010-06-18 21:14

    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
     }
    
    1. 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.

    2. Hash keys are always stringified. So, used as key to a hash, @$r[0] and "@$r[0]" are identical.

    3. 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}.

    点赞 打赏 评论

相关推荐 更多相似问题