SF1
SF1

Reputation: 469

Perl hash, array and references

I have this 3 lines of code in a sub and I'm trying to write them together on one line only.. but I'm quite lost

    my %p = @_;
    my $arr = $p{name};
    my @a = @$arr;

what's the correct way of doing this?

thank you!

Upvotes: 2

Views: 64

Answers (2)

Sinan Ünür
Sinan Ünür

Reputation: 118118

my %p = @_;

@_ is assumed to contain key-value pairs which are then used to construct the hash %p.

my $arr = $p{name};

The argument list is assumed to have contained something along the lines of name, [1, 2, 3,] so that $p{name} is an reference to an array.

my @a = @$arr;

Dereference that array reference to get the array @.

Here is an invocation that might work with this prelude in a sub:

func(this => 'that', name => [1, 2, 3]);

If you want to reduce the whole prelude to a single statement, you can use:

my @a = @{ { @_ }->{name} };

as in:

#!/usr/bin/env perl

use strict;
use warnings;

use YAML::XS;

func(this => 'that', name => [1, 2, 3]);

sub func {
    my @a = @{ { @_ }->{name} };
    print Dump \@a;
}

Output:

---
- 1
- 2
- 3

If the array pointed to by name is large, and if you do not need a shallow copy, however, it may be better to just stick with references:

my $aref = { @_ }->{ name };

Upvotes: 3

Sobrique
Sobrique

Reputation: 53478

OK so what you're doing is:

  • Assign a list of elements passed to the sub, to a hash.
  • extract a value from that hash (that appears to be an array reference)
  • dereference that into a standalone array.

Now, I'm going to have to make some guesses as to what you're putting in:

#!/usr/bin/perl

use warnings;
use strict;

use Data::Dumper;

sub test {
    my %p = @_;
    my $arr = $p{name};
    my @a = @$arr;
    print Dumper \@a; 
}

my %input = ( fish => [ "value", "another value" ],
              name => [ "more", "less" ], );

test ( %input ); 

So with that in mind:

sub test {
    print join "\n", @{{@_}->{name}},"\n";
}

But actually, I'd suggest what you probably want to do is pass in the hashref in the first place:

#!/usr/bin/perl

use warnings;
use strict;

use Data::Dumper;

sub test {
    my ( $input_hashref ) = @_;
    print Dumper \@{$input_hashref -> {name}};
}

my %input = ( fish => [ "value", "another value" ],
              name => [ "more", "less" ], );
test ( \%input ); 

Also:

  • Don't use single letter variable names. It's bad style.
  • that goes double for a and b because $a and $b are for sorting. (And using @a is confusing as a result).

Upvotes: 0

Related Questions