【问题标题】:Why can't I write @F[1..-1] to get elements 1..last?为什么我不能写 @F[1..-1] 来获取元素 1..last?
【发布时间】:2009-07-19 15:47:08
【问题描述】:

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

【问题讨论】:

    标签: perl arrays syntax notation


    【解决方案1】:

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

    【讨论】:

    • 我明白了,这太糟糕了。我认为 Perl 维护者仍应将其作为特例。
    • 它不需要是特殊情况,因为它已经很容易做到了:$a[1..$#a]。在下标括号中让事情以不同的方式工作是没有意义的。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:
      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

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

          规则是:

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

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

          @a[ empty set ]
          

          对应一个空数组切片。

          【讨论】:

            【解决方案6】:

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

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

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

            【讨论】:

            • 没有 [] 运算符。它只是围绕索引的括号。它对他们没有任何作用。它只接受一个列表。它不关心你如何列出清单。
            猜你喜欢
            • 2012-04-26
            • 1970-01-01
            • 1970-01-01
            • 2013-07-03
            • 2011-07-14
            • 1970-01-01
            • 2021-10-06
            • 2011-03-11
            相关资源
            最近更新 更多