为什么我不能写@F [1 ..- 1]来获取元素1..last?

Fra*_*ank 4 arrays syntax perl notation

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

@F=(1,2,3);
print $F[-1]; # result: 3
Run Code Online (Sandbox Code Playgroud)

您也可以使用$#符号,这里$#F:

@F=(1,2,3);
print $F[$#F]; # result: 3
Run Code Online (Sandbox Code Playgroud)

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

print @F[1..$#F]; # 23
print @F[1..-1];  # <empty>
Run Code Online (Sandbox Code Playgroud)

数组@F[1..-1]应该包含从元素1到最后一个元素的所有元素,不是吗?

Chr*_*isV 19

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

  • 它不需要是特殊情况,因为它已经很容易实现:$ a [1 .. $#a].在subscripty括号中使事情的工作方式不同是没有意义的. (4认同)

yst*_*sth 8

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

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


Bra*_*ert 5

print join ', ', 1..$#F; # 1, 2, 3, 4, 5, 6, ...
print join ', ', 1..-1;  #
Run Code Online (Sandbox Code Playgroud)

原因是' ..'运算符在数组下标中没有做任何特殊操作.

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


$#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 ) ]
Run Code Online (Sandbox Code Playgroud)

知道了这一点,您可以在范围运算符中使用变量:

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)
Run Code Online (Sandbox Code Playgroud)
2, 3

注意:这是一个不完整的示例,对于某些边缘情况,它将无法正常工作