2009-07-19 39 views
4

在Perl中,数组的索引-1意味着最后一个元素:为什么我不能写@F [1 ..- 1]来获取元素1..last?

@F=(1,2,3); 
print $F[-1]; # result: 3 

您还可以使用$#符号代替,这里$#F

@F=(1,2,3); 
print $F[$#F]; # result: 3 

那么,为什么不-1$#F给当我想指定范围中的最后一个元素时,结果相同:

print @F[1..$#F]; # 23 
print @F[1..-1]; # <empty> 

数组@F[1..-1]应该确实包含元素1中的所有元素到最后一个元素,否?

回答

19

你的问题是@a[b..c]语法涉及两个不同的操作。首先对b..c进行评估,返回一个列表,然后使用该列表对@a[]进行评估。范围运算符..不知道它用于数组下标,所以就它而言,1和-1之间没有任何内容。它返回空列表,所以数组返回一个空片。

+0

我明白了,那太糟糕了。我认为Perl维护者应该仍然把它作为一个特例来工作。 – Frank 2009-07-19 17:25:17

+4

它不需要特殊情况,因为它已经非常简单:$ a [1 .. $#a]。在下标括号中,使事情以不同的方式工作是没有意义的。 – 2009-07-19 17:42:08

0

[]运算符将接受单个索引或范围。

-1被接受为索引以表示最后一个元素的索引。正确的方法是$#F。

1 ..- 1的范围是空的,这就是为什么它不返回任何内容,因为范围评估与索引的评估是分开的。

+1

没有[]运算符。它只是指标周围的括号。它对他们没有任何帮助。它只接受一个列表。它不关心你如何列表。 – 2009-07-19 17:40:18

8

没有什么特别的..在数组切片;它只是生成请求的范围,然后查找该范围的切片。

@a[-3..-1]所以=>@a[-3,-2,-1],并@a[1..3] =>@a[1,2,3],但@a[1..-1]变得@a[()]

4

$#F是F的最后一个有效索引,而不是元素的数量。

@F =(1,2,3); #所以$#楼为2

5
print join ', ', 1..$#F; # 1, 2, 3, 4, 5, 6, ... 
print join ', ', 1..-1; # 

这样做的原因是,'..'运营商没有做数组下标什么特别的东西里面。

在列表上下文中,它返回从左值到右值计数(由1开始)的值列表。如果左侧值大于右侧值,则返回空列表。


$#F是最后一个元素,这是相同的长度减一“@F -1”的索引。 (如果长度是至少一种。)

$F[-1]仅仅是一个特殊的情况下,为了使之更容易得到在从另一端的元件,而不必手动计算位置。

$F[-1] === $F[ @F -1 ] === $F[ $#F ] 

@F[ 1 .. (@F -1) ] === @F[ 1 .. $#F ] 

@F[ 1 .. (@F -2) ] === @F[ 1 .. ($#F -1) ] 

认识到这一点,你可以在一个范围内运营商使用变量:

use strict; 
use warnings; 
use feature 'say'; 

sub list{ 
    my($arr,$first,$last) = @_; 

    $first = @$arr + $first if $first < 0; 
    $last = @$arr + $last if $last < 0; 

    return @$arr[ $first .. $last ]; 
} 

my @F = 1..3; 

say join ', ', list(\@F,1,-1) 
 
2, 3 

注:这是一个不完整的例子,它不会正确地对一些边缘情况下工作

2

规则是:

  • 如果数组索引是n上 - 负(或,等价地,大于$[更大),启动在阵列的开头开始计数
  • 如果是否定的,如果给定的范围内开始在端
  • 计数,返回数组切片

现在,就像(a,b)为空,如果a> b,则集合1 .. -1也是空的。因此,

@a[ empty set ] 

对应于一个空的数组切片。