在Perl中查找数组的大小


243

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

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

13
其他方法:print 0+@arrprint "".@arrprint ~~@arr
暴民

3
@mob,嗡嗡声,您可能想要避免"".@arr"@arr"但有些完全不同。
ikegami

39
“第二种方式”不是打印数组大小的方式...
tadmc 2011年

在标量上下文中; @arr返回表的大小。$ x = @ arr是标量上下文。$#arr返回数组的最后一个索引。从0开始的索引,则为真方程$#arr + 1 == @arr。如果您不按顺序写入某些元素,例如$ arr [100] ='any',则表将自动增加到最大索引100,并且(包括索引0)增加到101个元素。
Znik

Answers:


234

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

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


29
的大小(1,2,3)是3,并且索引是(默认)0,1和2。所以,$#ARR将是2在这种情况下,不3.
内特CK

5
预定义变量$[指定“数组中第一个元素的索引和子字符串中第一个字符的索引”(perldoc perlvar)。默认情况下将其设置为0,强烈不建议将其设置为0以外的任何值。
基思·汤普森

5
@Keith Thompson,$[不鼓励(已经十年了)。$[不推荐使用。使用会$[发出弃用警告,即使您没有打开警告也是如此。将零以外的任何值$[赋给5.16都会出错。我们可以停止提及$[了吗?
ikegami

2
@Keith Thompson,实际年龄大于5.14。但是就像我说的那样,不鼓励和弃用它的时间远远超过此,并且使用$[它的人也会知道它的作用。
ikegami

7
@ikegami:是的,但是有人试图了解两者之间的区别,scalar @arr并且仍然$#arr应该了解的可能影响,尽管这种情况很少见。$[
基思·汤普森

41

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

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

我个人更喜欢以下内容:

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

我发现比

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

my $size = @array;
say $size;

像这样,后者看起来很清晰,但是当发现其他代码的一部分时,我发现多余的一行会使其变得不清晰。这对于教授@array在标量上下文中执行的操作很有用,甚至在您要使用$size多次时也很有用。


15
就我个人而言,我更喜欢使用“ scalar”关键字的版本,因为它很明显是在强制使用标量上下文。my $size=@array使用错误的符号似乎是一个错误。
Nate CK

5
那真是个坏主意。scalar无缘无故使用的人会学到错误的教训。他们开始进入头脑,操作员返回可以强制转换为标量的列表。看过几十遍了。
ikegami 2014年

2
为什么这是“没有理由的”?您正在使用,scalar因为您将列表强制为标量上下文。这是使用它的正确原因。您的示例执行的操作完全相同,但是依赖于在隐式标量上下文中评估列表变量时Perl的操作。因此,您的示例要求读者了解该上下文中Perl的隐式行为。您只是在表达式中增加了一层隐式行为,而Perl已经有太多的隐式行为,您必须通过推理来解密程序。
Nate CK 2014年

2
@Nate CK,关于“为什么“没有理由”?您正在使用,scalar因为您正在将列表强制为标量上下文”,这证明了我在学习错误的课程方面的观点。这是完全错误的。没有任何列表可以强制执行scalar。(如果有,scalar(@array)并且scalar(@array[0..$#array])将返回相同的东西。)scalar(@array)告诉@array返回一个标量,你已经告诉它做my $size=
ikegami 2014年

2
信不信由你,开发人员必须调试其他开发人员编写的代码。开发人员必须调试他们三年前编写的代码。
Nate CK

27

这是通过将数组强制进入标量上下文来获得大小的,在该上下文中将其作为大小进行评估:

print scalar @arr;

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

my $arrSize = @arr;

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

print $#arr;

最后一个不是很好用来获取数组大小。如果只想获取数组的最后一个元素,它将很有用:

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

另外,正如您在此处的堆栈溢出中所看到的那样,大多数语法突出显示工具都无法正确处理此构造...


2
旁注:仅用于$arr[-1]获取最后一个元素。并$arr[-2]获得倒数第二个,依此类推。
tuomassalo 2015年

1
@tuomassalo:我同意您的建议是更好的方法。回想起来,$#arr这不是一个非常有用的功能,其他语言没有它也不是偶然的。
Nate CK 2015年

6

要使用第二种方法,请添加1:

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

for [0..$#array] { print $array[$_ ] } 如果获得元素数量的目的是遍历数组,则效果确实很好。好处是您可以获得对齐的元素和计数器。
Westrock,2016年

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;

5
这与这个答案和这个答案中已经提到的有什么不同吗?
devnull

5

例:

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

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

2

“Perl的变量类型”一节中的perlintro文件包含

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

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

您可能会倾向于使用它$#array + 1来告诉您数组中有多少个项目。不要打扰 碰巧的是,使用@arrayPerl期望在其中找到标量值的位置(“在标量上下文中”)将为您提供数组中元素的数量:

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

perldata文档还包括这个在“标量值”部分

如果您在标量上下文中求值数组,则它将返回数组的长度。(请注意,对于返回最后一个值(如C逗号运算符)的列表,对于内置函数(返回想要返回的值)而言,情况并非如此。)以下始终是正确的:

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

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

$element_count = scalar(@whatever);

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

数组的长度是标量值。您可以@days通过求值来找到数组的长度$#days,如中所示csh。但是,这不是数组的长度。它是最后一个元素的下标,这是一个不同的值,因为通常有第0个元素。


2

有多种打印数组大小的方法。这是全部的含义:假设我们的数组是my @arr = (3,4);

方法1:标量

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

print scalar @arr;  # prints size, here 2

方法2:索引号

$#arr给出数组的最后一个索引。因此,如果数组的大小为10,则其最后一个索引为9。

print $#arr;     # prints 1, as last index is 1
print $#arr + 1; # Add 1 to last index to get array size

我们在这里添加1,将array视为0-indexed。但是,如果它不是基于零的,那么此逻辑将失败

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

在上面的示例中显示6,因为我们将其初始索引设置为4。现在索引将是5和6,分别是元素3和4。

方法3:

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

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

实际上方法3和方法1是相同的。


2

从perldoc perldata中可以安全地引用:

以下始终是正确的:

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

只要您不使用$#what ++并神秘地增加大小或数组即可。

数组索引从0开始。

通过将空列表()分配给数组,可以将数组截断为零。以下是等效的:

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

这使我想到了要寻找的是如何检测数组为空的内容。如果$#empty == -1;



0

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

print scalar @array;

要找出数组的最后一个索引,请使用$#(Perl默认变量)。它给出了数组的最后一个索引。当数组从0开始时,我们通过在数组上加1来获得数组的大小$#

print "$#array+1";

例:

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

输出:

3

3
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.