0

我有一些代码,例如:

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

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

我看到它$values[0][0]持有美国并$values[0][1]持有 CA。为什么呢?请解释。

另外,我如何找出 的长度$values[0]

scalar $values[0]打印出诸如ARRAY(0x12FFc)blah..blah之类的东西...

任何链接也很有帮助。

4

4 回答 4

5

你是 Perl 的新手,而且你已经参考了...

在 Perl 中,有三种标准的数据类型:

  • 标量:这些可以包含单个值,例如$foo.
  • 数组:这些可以包含值列表。数组有一个顺序(这个值在数组中比这个值更早),并且值是根据它们在数组中的顺序(从第零项到最后一项)来引用的。您将数组称为@foo,将单个项目称为$foo[1]
  • 哈希:这些是键值。每个值都有一个唯一的键。没有顺序,但您可以根据其键快速找到一个值。您将散列称为%foo,将单个项目称为$foo{BAR}

请注意,所有这些都包含单独的值。数组或散列的每个元素只能有一个值。例如,我有一个主机哈希(USAmazonEUAmazon等),并且我希望每个主机都与一个国家($host{USAmazon} = 'US';$host{EUAmazon} =GB` 等)相关联。这在 Perl 中很容易实现。

不幸的是,事实并非如此。每台主机都可以与一系列国家代码相关联。如何将所有可能的国家/地区代码放入我的主机哈希中?这就是引用的来源。想象一下我有一个国家代码列表。如果我能找到该列表的内存位置,我可以将该内存位置用作我的哈希中的引用。因此,我的散列包含每个键的单个值。恰好键是特定列表在内存中的位置。

这就是引用的含义,以及为什么有时您会看到诸如ARRAY(0x12FFc). 这恰好是存储在哈希中的某个数组的内存位置。

有一个很好的关于参考的Perl 教程,它确实是标准 Perl 发行版的一部分。这是一个很好的起点。

一个快速的基本指南,虽然......

  • 您可以通过简单地在其前面放置一个反斜杠来获得对 Perl 变量类型的引用:

例如:

$reference_to_foo_array = \@foo;

如果我打印$reference_to_foo_array,我会得到类似的信息ARRAY(0x12FFc),告诉我这是内存位置的一个数组0x12FFc。但是,我现在可以将整个数组存储@foo到单个哈希或数组元素中:

$some_array[0] = $reference_to_foo_array;
  • 如果我有一个引用,我可以通过在它前面放置正确的变量类型符号将它转换回 Perl 变量。这称为取消引用

例如:

@another_array = @{$reference_to_foo_array};

在许多情况下,我可以消除花括号:

@another_array = @$reference_to_foo_array;

我可以有非常复杂的对象。例如。我有一个人的哈希值,每个哈希值都包含一个电话类型的哈希值。每个电话类型都包含该类型电话的列表。例如,我可能有两个工作电话号码和两个手机:

   $person{DAVID};

这是指大卫的电话。但是,这实际上是电话类型的哈希。如果我打印出来,我会得到类似的东西Hash(0x12b23)

如果我想要特定的电话类型,我会这样做:

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

这是大卫的手机号码列表。如果我打印这个,我会得到类似的东西,Array(0x3458b)因为它是一个电话号码数组的引用。

这里指的是大卫的第一部手机:

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

没有括号,你会看到:

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

幸运的是,Perl 有一个语法糖使它更容易阅读:

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

这表示有一个(人的)散列指代另一个(电话类型的)散列,该散列指的是电话号码数组。

Perl 还有一种无需实际命名即可创建散列或数组的方法。这将创建一个匿名哈希:

$phone{DAVID} = {};

现在,我可以得到 DAVID 的电话类型哈希值。以下是我创建匿名数组的方法:

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

现在,我可以得到 DAVID 的手机号码列表。

还有几件事:

  • 查看模块Data::Dumper。这可以帮助您打印出这些非常复杂的数据类型的结构,并帮助您了解您正在查看的内容。

  • 查看 Perl 函数ref。这可以帮助你弄清楚你在看什么。例如:

    我的 $data_type = ref $phone{DAVID}->{CELL}

将设置$data_typeARRAY。这让我知道这$phone{DAVID}->{CELL}不是电话号码,而是电话号码列表(或者可能是另一个引用类型的列表)。

于 2012-12-06T16:31:30.667 回答
3

数组和哈希值始终是标量。在这种情况下,对于现有元素,$hosts{$ARGV[0]}是一个包含对数组的引用的标量。您需要取消引用该引用以获取数组。

my $length = @{ $hosts{$ARGV[0]} };
于 2012-12-06T13:50:37.670 回答
0

%hostshash 将数组引用保存为值。您只需要取消引用它们:

my @values = @{$hosts{$ARGV[0]}};
于 2012-12-06T13:40:13.580 回答
-1

为了

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

$ARGV[0]您的哈希键之一在哪里,例如'USAmazon',您的哈希中的相应值%hosts将是

['US','CA']

这是一个匿名数组引用。此结构[ LIST ]用于创建用作标量值的数组引用,例如:

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

如果您要从现有数组中进行此操作,您也可以这样做:

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

但是,这将创建一个到命名数组的硬编码链接。使用匿名数组不会。

在散列(或数组)中,值只能是标量值。因此,如果您将哈希值分配给数组,则数组中的第一个元素将被分配该标量值。数组的第一个元素当然是$array[0]. 所以:

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)

有关详细信息,请参阅perldoc perldata

于 2012-12-06T14:08:58.887 回答