开发者

How can I access values in a 2-D Perl array so I can have them in scalar variables?

开发者 https://www.devze.com 2023-01-18 16:45 出处:网络
I seem to recall (though can\'t find any reference now) to one being able to do something akin to my @a = (\"foo\",\"bar\");

I seem to recall (though can't find any reference now) to one being able to do something akin to

my @a = ("foo","bar");
my ($item1, $item2) = @a;

The above does not do what I want it to (obviously) but I seem to recall that there is some way to do this, where it loads the items associated with the order of the scalars in the parenthesized list.

For that matter I thought that's how the args array is passed into subroutines, as in...

sub method{
  my ($arg1, $arg2) = @_;
}

Maybe I'm just going out of my mind, but I thought this was possible.

[EDIT]

Ah...so based 开发者_JAVA技巧on the first answer I realize that the reason it's not working is that I'm using a two dimensional array. So, in my code it actually looks like this:

foreach(@twoDimenArray){
    my ($item1, $item2, $item3) = $_; #$_ is an array
}

It must be the $ syntax that's screwing it up but I've tried ($_) and @($_) and @$_ and none of those work.


Try using @{$_}:

foreach (@twoDimenArray) {
    my ($item1, $item2, $item3) = @{$_};    # $_ is an array
}


What you have works for me - that is, this prints "foo bar":

use strict;
use warnings;

my @a = ("foo","bar");
my ($item1, $item2) = @a;

print "$item1 $item2\n";

I happen to be using Perl 5.13.4 on MacOS X 10.6.4, but I don't think that's a significant factor; I'd expect any Perl 5.x to accept it.


This code implements a 2D array:

use strict;
use warnings;

my @a;

$a[0][0] = "a00";
$a[0][1] = "a01";
$a[1][0] = "a10";
$a[1][1] = "a11";

my ($item1, $item2) = @a;

print "$item1 $item2\n";

The output is 'two ARRAY refs':

ARRAY(0x100803068) ARRAY(0x100826770)

Off-hand, I don't know of a way to expand the array of arrays into 4 separate values in a single operation. That isn't quite the same as "there is no way to do it".


And, implementing your foreach loop:

foreach my $array (@a)
{
    my($item1, $item2) = @$array;
    print "$item1 $item2\n";
}

This prints:

a00 a01
a10 a11

This code is an example from the DBD::Informix distribution - last modified in 2002. It uses the fetchall_arrayref() method which returns an array of array references, as mentioned in one of the comments to the question.

#!/usr/bin/perl -w
#
# DBD::Informix Example 5 - fetchall_arrayref
#
# @(#)$Id: x05fetchall_arrayref.pl,v 100.1 2002/02/08 22:50:10 jleffler Exp $
#
# Copyright 1998 Jonathan Leffler
# Copyright 2000 Informix Software Inc
# Copyright 2002 IBM

use DBI;
printf("DEMO1 Sample DBD::Informix Program running.\n");
printf("Variant 4: using fetchall_arrayref()\n");
my($dbh) = DBI->connect("DBI:Informix:stores7") or die;
my($sth) = $dbh->prepare(q%
        SELECT fname, lname FROM customer WHERE lname < 'C'%) or die;
$sth->execute() or die;
my($ref) = $sth->fetchall_arrayref();
foreach $row (@$ref)
{
  printf("%s %s\n", $$row[0], $$row[1]);
}
undef $sth;
$dbh->disconnect();
printf("\nDEMO1 Sample Program over.\n\n");

Were I writing it now (or updating it), there'd be use use strict; as well as the -w (equivalent to use warnings;). It shows that back in 2002 (and ever since, AFAIK), you could write @$ref happily enough. These days, I'd probably write the $$row[0] references differently - as ${$row}[0].


For an array of array refs:

#!/usr/bin/perl

use strict;
use warnings;

my @ary = ( [ qw( foo bar ) ], [ qw( one two ) ], );

my ($ary00, $ary01, $ary10, $ary11) = map { @{ $_ } } @ary;

For arbitrarily-nested arrays:

#!/usr/bin/perl

use strict;
use warnings;

my @ary = (
    [
        qw( foo bar ),
        [
            qw( BAZ QUUX )
        ],
    ],
    [
        qw( ten eleven ),
        [
            'one hundred and twenty',
            'one hundred and twenty-one',
            [
                'one thousand two hundred and twenty',
                'one thousand two hundred and twenty-one',
            ],
        ],
    ],
);

sub flatten {
    my @ary = @_;
    return map { ref($_) eq 'ARRAY' ? flatten( @{ $_ } ) : @{ $_ } } @ary;
}

my ( $a00, $a01, $a020, $a021, $a10, $a11, $a120, $a121, $a1220, $a1221 ) = flatten @a;
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号