简体   繁体   中英

Find length of array in Perl

I have some code like:

my %hosts = (
    'USAmazon' => ['US','CA'],
    'EUAmazon' => ['GB', 'FR', 'IT', 'ES', 'DE'],
    'CNAmazon' => ['CN'],
    'JPAmazon' => ['JP'],
);

my @values = $hosts{$ARGV[0]};

I see that $values[0][0] holds US and $values[0][1] holds CA. Why is that so? Please explain.

Also, how do I find out the length of $values[0] ?

scalar $values[0] prints out something like ARRAY(0x12FFc) blah..blah...

Any links are also helpful.

You're a newbie in Perl, and you've already hit references ...

In Perl, there are three standard types of data:

  • Scalars : These can contain a single value such as $foo .
  • Arrays : These can contain a list of values. The array has an order (this value is earlier in the array than this value), and values are referenced based upon their order in the array (from the zeroth item to the last item). You refer to the array as @foo and to an individual item as $foo[1] .
  • Hashes : These are keyed values. Each value has a unique key. There is no order, but you can quickly find a value based upon its key. You refer to the hash as %foo and to an individual item as $foo{BAR} .

Note that all of these contain individual values. Each element of an array or hash can only have a single value. For example, I have a hash of host machines ( USAmazon , EUAmazon , etc), and I would like each host to be associated with a single country ( $host{USAmazon} = 'US'; , $host{EUAmazon} = GB`, etc.). That's simple and easy to implement in Perl.

Unfortunately, it's also not the case. Each host machine can be associated with a whole array of country codes. How do I put that whole array of possible country codes into my hash of host machines? This is where references come in. Imagine I have a list of country codes. If I could find the memory location of that list, I could use that memory location as a reference in my hash. Thus, my hash contains a single value for each key. It just happens that the key is the location in memory to a particular list.

This is what references are, and why you sometimes see a value such as ARRAY(0x12FFc) . That happens to be a memory location of some array that is stored in your hash.

There is a nice Perl tutorial on references that is really part of the standard Perl distribution. This is an excellent place to start.

A quick basic guide, though...

  • You can get a reference to a Perl variable type by simply putting a backslash in front of it:

For example:

$reference_to_foo_array = \@foo;

If I print $reference_to_foo_array , I get something like ARRAY(0x12FFc) which tells me this is an array at the memory location 0x12FFc . However, I can now store my entire array @foo into a single hash or array element:

$some_array[0] = $reference_to_foo_array;
  • If I have a reference, I can convert it back into a Perl variable by putting the correct variable type sign in front of it. This is called dereferencing .

For example:

@another_array = @{$reference_to_foo_array};

In many cases, I can eliminate the curly braces:

@another_array = @$reference_to_foo_array;

I can have very complex objects. For example. I have a hash of people, each hash contains a hash of phone types. Each phone type contains a list of phones of that type. For example, I might have two work phone numbers and two cell phones:

   $person{DAVID};

This refers to the phones of DAVID. However, this is actually a hash of phone types. If I print this out, I'd get something like Hash(0x12b23) :

If I want a particular phone type, I would do this:

 ${$person{DAVID}}{CELL};

This is a list of David's cell phone numbers. If I print this, I'd get something like Array(0x3458b) because it's a reference an array of phone number.

This refers to the first cell phone of DAVID:

${${$phone{DAVID}}{CELL}}[0];

Without the parentheses, you'd see this:

$$$phone{DAVID}{CELL}[0];

Fortunately, Perl has a syntactic sugar that makes it easier to read:

$phone{DAVID}->{CELL}->[0];

This says there's a hash (of people) that refers to another hash (of phone types) that refers to an array of phone numbers.

Perl also has a way of creating a hash or an array without actually naming it. This creates an anonymous hash:

$phone{DAVID} = {};

Now, I can have a hash of phone types for DAVID. Here's how I create an anonymous array :

$phone{DAVID}->{CELL} = [];

Now, I can have a list of cell phone numbers for DAVID.

A few more things:

  • Look at the module Data::Dumper . This helps you print out the structure of these very complex data types and helps you understand what you're looking at.

  • Look at the Perl function ref . This can help you figure out what you're looking at. For example:

    my $data_type = ref $phone{DAVID}->{CELL}

will set $data_type to ARRAY . This lets me know that $phone{DAVID}->{CELL} isn't a phone number, but instead is a list of phone numbers (or maybe a list of another reference type).

Array and hash values are always scalars. In this case, for existing elements, $hosts{$ARGV[0]} is a scalar containing a reference to an array. You need to dereference that reference to get the array.

my $length = @{ $hosts{$ARGV[0]} };

%hosts hash holds array references as values. You only need to dereference them:

my @values = @{$hosts{$ARGV[0]}};

For

my @values = $hosts{$ARGV[0]};

Where $ARGV[0] is one of the keys of your hash, eg 'USAmazon' , the corresponding value in your %hosts hash will be

['US','CA']

Which is an anonymous array reference. This structure, [ LIST ] is used to create an array reference to be used as a scalar value, eg:

my $foo = [ 1, 2, 3 ];    # $foo is a scalar

If you were to make this from an existing array you might also do:

my @foo = (1, 2, 3);      # @foo is an array
my $foo = \@foo;          # reference to an array @foo

However this will make a hard coded link to the named array. Using anonymous arrays will not.

In a hash (or array), the values can only be scalar values. So if you assign a hash value to an array, the first element in the array will be assigned that scalar value. The first element of the array is of course $array[0] . So:

my $foo = $hosts{$ARGV[0]};   # [ 'US', 'CA' ]
my @bar = $foo;
print $bar[0];                # prints the array reference ARRAY(...)
print $foo;                   # same thing
print $foo->[0];              # 'US'
print $bar[0][0];             # 'US' (same thing)

For more information, see perldoc perldata .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM