为什么perl仅在使用范围运算符时取消引用最后一个索引?

时间:2015-07-22 17:13:38

标签: perl

我有一个数组引用的数组@array。如果我使用范围运算符打印@arrayprint @array[1..3]的元素1到3,perl将打印元素1到3的数组引用。

为什么当我尝试取消引用索引在1和3之间的数组引用@{@array[1..3]}时,perl只取消引用并打印出范围运算符中索引的最后一个元素?

在取消引用数组时,有没有办法使用范围运算符?

示例代码

#!/bin/perl

use strict;
use warnings;

my @array = ();
foreach my $i (0..10) {
    push @array, [rand(1000), int(rand(3))];
}

foreach my $i (@array) {
    print "@$i\n";
}

print "\n\n================\n\n";

print @{@array[1..3]};

print "\n\n================\n\n";

4 个答案:

答案 0 :(得分:5)

来自perldata

  

标量上下文中的切片返回切片的最后一项。

@{ ... }标量值取消引用为数组,这意味着被解除引用的值位于标量上下文中。从上面的perldata引用我们知道这将返回最后一个元素。因此结果是最后一个元素。

更合理的方法是遍历切片并打印每个单独的数组引用:

use strict; 
use warnings; 

use feature qw(say);

my @array_of_arrayrefs = (
   [qw(1 2 3)],
   [qw(4 5 6)],
   [qw(7 8 9)],
   [qw(a b c)],
);

foreach my $aref ( @array_of_arrayrefs[1..3] ) {
   say join ',', @$aref;
}

答案 1 :(得分:3)

@{@array[1..3]}是一个看起来很奇怪的结构。 @{ ... }是数组解除引用运算符。它需要一个引用,这是一种标量。但是@array[ ... ]会生成一个列表。

这是您需要记住标量上下文中的列表评估规则的情况之一。规则是没有一般规则。每个生成列表的运算符都有自己的功能。在这种情况下,显然在标量上下文中使用的数组切片运算符返回列表的最后一个元素。标量上下文中的@array[1..3]$array[3]相同。

正如您所注意到的,这没用。数组切片并不意味着在标量上下文中使用

如果要将二维嵌套数组结构展平为一维列表,请使用map

print join ' ', map { @$_ } @array[1..3]

您仍然使用范围运算符进行切片。您只需要某种循环结构(例如map)将数组解引用运算符分别应用于外部数组的每个元素。

答案 2 :(得分:1)

@{ ... }构造将大括号内的代码的标量值取消引用为数组

我不清楚您对@{ @array[1..3] }的期望,但标量上下文中的列表@array[1..3]仅返回列表的最后一个元素 - $array[3] - 所以你要求@{ $array[3] },我想你得到了什么

如果您解释想要打印的内容,那么我相信我们可以提供帮助,但取消引用列表毫无意义

答案 3 :(得分:1)

@array[1..3]是3个数组引用的列表。你不能一次取消引用它们,所以你应该迭代这个列表并分别取消引用每个元素:

print @$_ for @array[1..3];
print "@$_\n" for @array[1..3];  # for better looking output