在Perl中查找数组的大小

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

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
620272 次浏览

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

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

这个函数通过强制数组进入一个标量上下文来获取数组的大小,在这个上下文中数组的值是数组的大小:

print scalar @arr;

这是另一种强制数组进入标量上下文的方式,因为它被赋值给一个标量变量:

my $arrSize = @arr;

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

print $#arr;

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

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

此外,正如你在Stack Overflow上看到的,大多数语法高亮显示器都不能正确处理这个构造……

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

另外两个(scalar @arr$arrSize = @arr)实际上是相同的。您只是使用了两种不同的方法来创建标量上下文。这归结为可读性的问题。

我个人更喜欢以下几点:

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

我发现它比

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

而且

my $size = @array;
say $size;

后者像这样单独看起来非常清楚,但我发现当与其他代码一起使用时,额外的行会降低清晰度。它有助于教授@array在标量上下文中做什么,或者如果你想多次使用$size的话。

例子:

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


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

使用第二种方法,加1:

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

如果我们稍微修改一下第二个,这三个结果都是一样的:

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;

perlintro文档“Perl变量类型”部分包含

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

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

你可能会想用$#array + 1来告诉你数组中有多少项。不用麻烦了。当它发生时,使用@array, Perl期望在其中找到一个标量值(“在标量上下文中”),将为您提供数组中元素的数量:

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

perldata文档“标量值”部分中也包含了这个。

如果在标量上下文中计算数组,则返回数组的长度。(注意,列表不是这样的,它返回最后一个值,比如C逗号操作符;内置函数也不是这样,它返回它们想返回的任何值。)下面这句话总是正确的:

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

一些程序员选择使用显式转换,以便不留任何疑问:

$element_count = scalar(@whatever);

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

数组的长度是一个标量值。你可以通过计算$#days找到数组@days的长度,就像在csh中一样。然而,这不是数组的长度;它是最后一个元素的下标,这是一个不同的值,因为通常有第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

从perldoc perldata,引用它应该是安全的:

下面这句话总是正确的:

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

只要你不使用$#,然后神秘地增加数组的大小。

数组下标从0开始。

而且

通过给数组赋值空列表(),可以将数组截断为空。以下是等价的:

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

这让我想到了我一直在寻找的东西即如何检测数组是否为空。我发现如果$#empty == -1;

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

假设数组是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,将数组视为也就是。但是,如果它不是从零开始的,则这个逻辑会失败

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

实际上,方法三和方法一是一样的。

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

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

在这里,我将用一些用法示例来扩展这些答案。

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

下面是标量上下文的一些例子,比如在ifunless中单独使用@array_name,或者在算术比较中使用==!=

如果你将@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