开发者

How can I dereference an array of arrays in Perl?

开发者 https://www.devze.com 2023-01-20 11:17 出处:网络
How do I dereference an array of arrays when passed to a function? I am doing it like this: my @a = {\\@array1, \\@array2, \\@array3};

How do I dereference an array of arrays when passed to a function?

I am doing it like this:

my @a = {\@array1, \@array2, \@array3};

func(\@a);


func{
    @b = @_;

    @c = @{@b};
}

Actual开发者_运维技巧ly I want the array @c should contain the addresses of @array1, @array2, and @array3.


my @a = {\@array1, \@array2, \@array3};

The above is an array with a single member -> a hash containing:

{ ''.\@array1 => \@array2, ''.\@array3 => undef }

Because as a key in the hash, Perl coerces the reference to @array1 into a string. And Perl allows a scalar hash reference to be assigned to an array, because it is "understood" that you want an array with the first element being the scalar you assigned to it.

You create an array of arrays, like so:

my @a = (\@array1, \@array2, \@array3);

And then in your function you would unpack them, like so:

sub func {
    my $ref = shift;
    foreach my $arr ( @$ref ) {
        my @list_of_values = @$arr;
    }
}

Or some variation thereof, like say a map would be the easiest expression:

my @list_of_entries = map { @$_ } @$ref;

In your example, @c as a list of addresses is simply the same thing as a properly constructed @a.


You may want to read perldoc perlreftut, perldoc perlref, and perldoc perldsc You can say:

sub func {
    my $arrayref = shift;

    for my $aref (@$arrayref) {
        print join(", ", @$aref), "\n";
    }
}

my @array1 = (1, 2, 3);
my @array2 = (4, 5, 6);
my @array3 = (7, 8, 9);

my @a = \(@array1, @array2, @array3);

func \@a;

or more compactly:

sub func {
    my $arrayref = shift;

    for my $aref (@$arrayref) {
        print join(", ", @$aref), "\n";
    }
}

func [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ];


Read the perlreftut documentation.

Edit: Others point out a good point I missed at first. In the initialization of @a, you probably meant either @a = (...) (create array containing references) or $arrayref = [...] (create reference to array), not {...} (create reference to hash). The rest of this post pretends you had the @a = (...) version.

Since you pass one argument (a reference to @a) to func, @_ is a list containing that one reference. You can get that reference and then dereference it by doing:

sub func {
  my $arrayref = shift;
  my @c = @{$arrayref};
}

Or in one line, it would look like:

sub func {
  my @c = @{shift()};
}

(If you hadn't used the backslash in func(\@a), @_ would be equal to @a, the array of three references.)


The following function is designed to take either an array or an array reference and give back a sorted array of unique values. Undefined values are removed and HASH and GLOB are left as is.

#!/usr/bin/perl
use strict; use warnings;

my @one = qw / dog rat / ;
my @two = qw / dog mice / ;
my @tre = ( "And then they said it!", "No!??  ", );
open my $H, '<', $0 or die "unable to open $0 to read";
my $dog; # to show behavior with undefined value
my %hash; $hash{pig}{mouse}=55; # to show that it leaves HASH alone
my $rgx = '(?is)dog'; $rgx = qr/$rgx/; # included for kicks

my @whoo =  (
    'hey!',
    $dog, # undefined
    $rgx,
    1, 2, 99, 999, 55.5, 3.1415926535,
    %hash,
    $H,
    [ 1, 2, 
              [ 99, 55, \@tre, ],
    3, ],
        \@one, \@two,
        [ 'fee', 'fie,' ,
            [ 'dog', 'dog', 'mice', 'gopher', 'piranha', ],
            [ 'dog', 'dog', 'mice', 'gopher', 'piranha', ],
        ],
        [ 1, [ 1, 2222, ['no!', 'no...', 55, ], ], ],
        [ [ [ 'Rat!', [ 'Non,', 'Tu es un rat!' , ], ], ], ], 
        'Hey!!',
        0.0_1_0_1,
        -33,
);


print join ( "\n", 
    recursively_dereference_sort_unique_array( [ 55, 9.000005555, ], @whoo, \@one, \@whoo, [ $H ], ),
    "\n", );
close $H;
exit;

sub recursively_dereference_sort_unique_array
{
    # recursively dereference array of arrays; return unique values sorted. Leave HASH and GLOB (filehandles) as they are.
    # 2020v10v04vSunv12h20m15s
    my $sb_name = (caller(0))[3];
    @_ = grep defined, @_; #https://stackoverflow.com/questions/11122977/how-do-i-remove-all-undefs-from-array
    my @redy = grep { !/^ARRAY\x28\w+\x29$/ } @_; # redy==the subset that is "ready"
    my @noty = grep {  /^ARRAY\x28\w+\x29$/ } @_; # noty==the subset that is "not yet"
    my $countiter = 0;
    while (1)
    {
        $countiter++; 
        die "$sb_name: are you in an infinite loop?" if ($countiter > 99);
        my @next;
        foreach my $refarray ( @noty )
        {
            my @tmparray = @$refarray;
            push    @next, @tmparray;
        }
        @next = grep defined, @next;
        my @okay= grep { !/^ARRAY\x28\w+\x29$/ } @next;
        @noty   = grep {  /^ARRAY\x28\w+\x29$/ } @next;
        push @redy, @okay;
        my %hash = map { $_ => 1 } @redy; # trick to get unique values
        @redy    = sort keys %hash;
        return @redy unless (scalar @noty);
    }
}


Should be

func {
    $b = shift;
}

if you're passing in a reference. Hope that helps some.

0

精彩评论

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

关注公众号