【问题标题】:Find size of an array in Perl在 Perl 中查找数组的大小
【发布时间】:2011-11-16 10:25:24
【问题描述】:

我似乎遇到了几种不同的方法来查找数组的大小。这三种方法有什么区别?

my @arr = (2);
print scalar @arr; # First way to print array size

print $#arr; # Second way to print array size

my $arrSize = @arr;
print $arrSize; # Third way to print array size

【问题讨论】:

  • 其他方式:print 0+@arrprint "".@arrprint ~~@arr
  • @mob,嗯,可能有人想避免"".@arr,因为"@arr" 做了一些完全不同的事情。
  • “第二种方式”不是打印数组大小的方式...
  • 在标量上下文中;@arr 返回表大小。 $x=@arr 是标量上下文。 $#arr 返回数组的最后一个索引。索引从 0 开始,然后是真正的方程式 $#arr+1 == @arr 。如果你乱写了一些元素,例如 $arr[100]='any',那么 table 会自动增加到最大索引 100,并且(包括索引 0)增加到 101 个元素。
  • 这个问题出现在搜索引擎结果中,但似乎不太可能没有更早的问题,从 Stack Overflow 存在的头两年开始。有哪些候选人?

标签: perl


【解决方案1】:

第一种和第三种方法是相同的:它们在标量上下文中评估一个数组。我认为这是获取数组大小的标准方法。

第二种方式实际上返回数组的最后一个索引,它(通常)与数组大小不同。

【讨论】:

  • (1,2,3) 的大小为 3,索引(默认)为 0、1 和 2。因此,在这种情况下,$#arr 将为 2,而不是 3。
  • 预定义变量$[ 指定“数组中第一个元素的索引,以及子字符串中第一个字符的索引”(perldoc perlvar)。它默认设置为 0,强烈建议不要将其设置为 0 以外的任何值。
  • @Keith Thompson, $[ 不鼓励(并且已经有十年了)。 $[ 已弃用。即使没有打开警告,使用$[ 也会发出弃用警告。在 5.16 中,将除零以外的任何值分配给 $[ 将是一个错误。我们可以停止提及$[ 了吗?
  • @Keith Thompson,实际上早于 5.14。但就像我说的那样,它被劝阻和弃用的时间远比这要长得多,使用$[ 的人会知道它的影响。
  • @ikegami:是的,但是试图了解scalar @arr$#arr 之间区别的人应该仍然了解$[ 的可能影响,尽管它们很少见.
【解决方案2】:

首先,第二个不等于其他两个。 $#array 返回数组的最后一个索引,比数组的大小小一。

其他两个几乎相同。您只是使用两种不同的方法来创建标量上下文。这归结为可读性问题。

我个人更喜欢以下:

say 0+@array;          # Represent @array as a number

我觉得比

say scalar(@array);    # Represent @array as a scalar

my $size = @array;
say $size;

后者像这样单独看起来很清晰,但我发现当其他代码的一部分时,额外的行会导致清晰。它对于教授 @array 在标量上下文中的作用非常有用,也许如果您想多次使用 $size

【讨论】:

  • 我个人更喜欢使用“scalar”关键字的版本,因为它非常明确地强制使用标量上下文。 my $size=@array 看起来可能是使用了错误的印记。
  • 这真是个坏主意。无缘无故使用scalar 的人吸取了错误的教训。他们开始意识到运算符返回的列表可以强制转换为标量。看了几十遍了。
  • 为什么这是“没有理由”?您正在使用scalar,因为您将列表强制为标量上下文。这是使用它的正确理由。您的示例做了完全相同的事情,但依赖于 Perl 在隐式标量上下文中评估列表变量时所做的事情。因此,您的示例要求读者了解 Perl 在该上下文中的隐含行为。您只是在表达式中添加了一层隐含行为,而 Perl 已经有太多隐含行为,您必须通过推理才能破译程序。
  • @Nate CK,关于“为什么这是“没有理由”?您使用 scalar 是因为您将列表强制为标量上下文”,您证明了我关于学习错误的观点课。这是完全错误的。 scalar 从未强制列出任何列表。 (如果是这样,scalar(@array)scalar(@array[0..$#array]) 将返回相同的内容。)scalar(@array) 告诉 @array 返回一个标量,您已经告诉它与 my $size= 相关。
  • 信不信由你,开发人员必须调试其他开发人员编写的代码。而且开发人员必须调试他们三年前编写的代码。
【解决方案3】:

这通过强制数组进入一个标量上下文来获取大小,在其中它被评估为其大小:

print scalar @arr;

这是强制数组进入标量上下文的另一种方法,因为它被分配给标量变量:

my $arrSize = @arr;

这将获取数组中最后一个元素的索引,因此它实际上是大小减 1(假设索引从 0 开始,这在 Perl 中是可调整的,尽管这样做通常是个坏主意):

print $#arr;

最后一个不太适合用于获取数组大小。如果您只想获取数组的最后一个元素,这将很有用:

my $lastElement = $arr[$#arr];

此外,正如您在 StackOverflow 上看到的,大多数语法高亮显示都无法正确处理此构造...

【讨论】:

  • 附注:只需使用$arr[-1] 获取最后一个元素。和$arr[-2] 获得倒数第二个,依此类推。
  • @tuomassalo:我同意您的建议是更好的方法。回想起来,$#arr 并不是一个非常有用的功能,其他语言没有它也并非偶然。
【解决方案4】:

要使用第二种方式,加1:

print $#arr + 1; # Second way to print array size

【讨论】:

  • for [0..$#array] { print $array[$_ ] } 工作得非常好,但如果获取元素数量的目的是遍历数组。优点是您可以获得对齐的元素和计数器。
【解决方案5】:

如果我们稍微修改第二个,所有三个都会给出相同的结果:

my @arr = (2, 4, 8, 10);

print "First result:\n";
print scalar @arr; 

print "\n\nSecond result:\n";
print $#arr + 1; # Shift numeration with +1 as it shows last index that starts with 0.

print "\n\nThird result:\n";
my $arrSize = @arr;
print $arrSize;

【讨论】:

  • 这与this 答案和this one 中已经提到的有什么不同吗?
【解决方案6】:

例子:

my @a = (undef, undef);
my $size = @a;

warn "Size: " . $#a;   # Size: 1. It's not the size
warn "Size: " . $size; # Size: 2

【讨论】:

    【解决方案7】:

    perlintro documentation 中的“Perl variable types” section 包含

    特殊变量$#array告诉你数组最后一个元素的索引:

    print $mixed[$#mixed];       # last element, prints 1.23
    

    您可能很想使用$#array + 1 来告诉您数组中有多少项。不要打扰。碰巧的是,使用 @array Perl 期望找到一个标量值(“在标量上下文中”)将为您提供数组中元素的数量:

    if (@animals < 5) { ... }
    

    perldata documentation 也在 “Scalar values” section 中介绍了这一点。

    如果在标量上下文中计算数组,它会返回数组的长度。 (请注意,列表不是这样,它返回最后一个值,如 C 逗号运算符,也不是内置函数,它返回他们想要返回的任何内容。)以下总是正确的:

    scalar(@whatever) == $#whatever + 1;
    

    一些程序员选择使用显式转换以便毫无疑问:

    $element_count = scalar(@whatever);
    

    同一部分的前面部分介绍了如何获取数组最后一个元素的索引。

    数组的长度是一个标量值。您可以通过评估$#days 找到数组@days 的长度,如csh。然而,这不是数组的长度;它是最后一个元素的下标,这是一个不同的值,因为通常有第 0 个元素。

    【讨论】:

      【解决方案8】:

      来自 perldoc perldata,引用应该是安全的:

      以下内容总是正确的:

      scalar(@whatever) == $#whatever + 1;
      

      只要您不 $#whatever++ 并神秘地增加大小或数组。

      数组索引从 0 开始。

      您可以通过将空列表 () 分配给它来将数组截断为空。以下是等价的:

          @whatever = ();
          $#whatever = -1;
      

      这让我想到了如何检测数组是否为空。我发现它 if $#empty == -1;

      【讨论】:

        【解决方案9】:

        有多种方法可以打印数组的大小。以下是所有的含义:

        假设我们的数组是my @arr = (3,4);

        方法一:标量

        这是获取数组大小的正确方法。

        print scalar @arr;  # Prints size, here 2
        

        方法二:索引号

        $#arr 给出数组的最后一个索引。因此,如果数组的大小为 10,那么它的最后一个索引将是 9。

        print $#arr;     # Prints 1, as last index is 1
        print $#arr + 1; # Adds 1 to the last index to get the array size
        

        我们在这里添加 1,将数组视为 0-indexed。但是,如果它不是从零开始的,这个逻辑就会失败

        perl -le 'local $[ = 4; my @arr = (3, 4); print $#arr + 1;'   # prints 6
        

        上面的例子打印了 6,因为我们已经将它的初始索引设置为 4。现在索引将是 5 和 6,元素分别是 3 和 4。

        方法三:

        在标量上下文中使用数组时,它会返回数组的大小

        my $size = @arr;
        print $size;   # Prints size, here 2
        

        其实方法三和方法一是一样的。

        【讨论】:

          【解决方案10】:

          使用int(@array),因为它以标量形式威胁参数。

          【讨论】:

            【解决方案11】:

            要查找数组的大小,请使用 scalar 关键字:

            print scalar @array;
            

            要找出数组的最后一个索引,有$#(Perl 默认变量)。它给出了数组的最后一个索引。由于数组是从 0 开始的,我们通过在$# 上加一来得到数组的大小:

            print "$#array+1";
            

            例子:

            my @a = qw(1 3 5);
            print scalar @a, "\n";
            print $#a+1, "\n";
            

            输出:

            3
            
            3
            

            【讨论】:

            • "Perl 默认变量"是什么意思?
            【解决方案12】:

            正如许多答案所指出的,第一种和第三种方法是获取数组大小的正确方法,而第二种方法不是。

            在这里,我通过一些使用示例来扩展这些答案。

            @array_name 计算结果为数组的长度 = 数组的大小 = 数组中的元素数,在标量上下文中使用时

            以下是标量上下文的一些示例,例如 @array_name 本身在 ifunless 中,在算术比较中,例如 ==!=

            如果您将@array_name 更改为scalar(@array_name),所有这些示例都将起作用。这将使代码更明确,但也更长且可读性稍差。因此,这里首选省略scalar() 的更惯用用法。

            my @a = (undef, q{}, 0, 1);
            
            # All of these test whether 'array' has four elements:
            print q{array has four elements} if @a == 4;
            print q{array has four elements} unless @a != 4;
            @a == 4 and print q{array has four elements};
            !(@a != 4) and print q{array has four elements};
            
            # All of the above print:
            # array has four elements
            
            # All of these test whether array is not empty:
            print q{array is not empty} if @a;
            print q{array is not empty} unless !@a;
            @a and print q{array is not empty};
            !(!@a) and print q{array is not empty};
            
            # All of the above print:
            # array is not empty
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-12-13
              • 1970-01-01
              • 2011-07-16
              • 2012-06-26
              • 2021-11-29
              • 1970-01-01
              • 2023-04-07
              相关资源
              最近更新 更多