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:
$foo
. @foo
and to an individual item as $foo[1]
. %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...
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;
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.