4

在 Perl 中,数组索引-1表示最后一个元素:

@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到最后一个元素的所有元素,不是吗?

4

6 回答 6

19

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

于 2009-07-19T16:08:17.440 回答
8

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

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

于 2009-07-19T16:10:34.003 回答
5
print join ', ', 1..$#F; # 1, 2, 3, 4, 5, 6, ...
print join ', ', 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

注意:这是一个不完整的示例,它在某些极端情况下无法正常工作

于 2009-07-19T16:50:12.897 回答
4

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

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

于 2009-07-19T16:32:05.147 回答
2

规则是:

  • 如果数组索引为非负数(或等价地大于$[),则从数组的开头开始计数
  • 如果是负数,从最后开始计数
  • 如果给定一个范围,则返回一个数组切片

现在,就像集合(a,b)如果a > b为空一样,集合1 .. -1也是空的。所以,

@a[ empty set ]

对应于一个空数组切片。

于 2009-07-19T21:51:02.727 回答
0

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

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

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

于 2009-07-19T16:08:14.993 回答