如何在Perl列表中找到值的数量?

时间:2010-02-08 22:43:34

标签: perl list

列表中的值的数量只能通过迭代其值或将其转换为数组来确定。将其分配给标量不会返回项目计数:

my $n = ('a', 'b', 'c');  # $n = 'c' 

有一个“空括号”的习语,可以用来获取元素的数量:

my $n = () = ('a', 'b', 'c'); # $n = 3

它在内部等同于

my $n = @{[ 'a', 'b', 'c' ]};

7 个答案:

答案 0 :(得分:8)

您展示的两个项目并不相同。但他们有相同的最终结果;

my $n = @{[ 'a', 'b', 'c' ]};

在这里创建一个匿名数组[ 'a', 'b', 'c' ],然后取消引用它并获取成员数。数组的创建为语句中的逗号运算符提供了一个列表上下文。

my $n = () = ('a', 'b', 'c');

这里我们使用臭名昭着的“山羊运营商”。列表('a', 'b', 'c')已分配给空列表() = ('a', 'b', 'c');。列表分配的结果分配给$n。列表赋值返回标量上下文中赋值右侧的项目数(在列表上下文中,您将获得分配给的值列表)。

答案 1 :(得分:6)

这是一个有趣的实现细节:对空列表的赋值是否会创建(不必要的)匿名数组?

有两种方法可以回答这个问题:首先,正确的方法:尝试弄清楚如何在源中处理这个问题。 是否有一个特殊情况可以分配给在标量上下文中评估的空列表?

作为懒惰和无知的类型,我选择使用Benchmark

#!/usr/bin/perl

use strict; use warnings;
use Benchmark qw( cmpthese );

cmpthese -5,  {
    goatse => sub { my $n = () = 'A' .. 'Z' },
    anon   => sub { my $n = @{[ 'A' .. 'Z' ]}},
};

我经常运行基准测试,并且在所有情况下,对空列表的分配都略有优势。如果差异纯粹是随机的,那么观察10个时间的概率都有利于 goatse 小于0.1%,所以我假设存在某种短路。

另一方面,正如在评论中发布的运行基准@daotoad,可能会给出更完整的图片:

#!/usr/bin/perl

use strict; use warnings;
use Benchmark qw( cmpthese );

use constant START => 1;
use constant STOP => 1000;

my $start = START;
my $stop = STOP;

cmpthese -5, {
    anon => sub { my $n = @{[ $start .. $stop ]}},
    goatse => sub { my $n = () = $start .. $stop },
    canon => sub { my $n = @{[ START .. STOP ]}},
    cgoatse => sub { my $n = () = START .. STOP },
};

我机器上的典型结果(Windows XP Pro SP3,Core 2 Duo,2 Gb内存,ActiveState perl 5.10.1.1006):

           Rate    anon cgoatse  goatse   canon
anon     5207/s      --    -45%    -49%    -51%
cgoatse  9522/s     83%      --     -7%    -10%
goatse  10201/s     96%      7%      --     -4%
canon   10636/s    104%     12%      4%      --

并且:用:

use constant START => 'AAAA';
use constant STOP => 'ZZZZ';

结果是:

          Rate    anon  goatse cgoatse   canon
anon    1.73/s      --    -12%    -16%    -17%
goatse  1.98/s     14%      --     -4%     -5%
cgoatse 2.06/s     19%      4%      --     -1%
canon   2.08/s     20%      5%      1%      --

结论:

如有疑问,请使用my $n = () = ...;

答案 2 :(得分:4)

没有。它相当于:

my $n = (() = ('a', 'b', 'c'));

...因为赋值运算符是右关联的。右侧带括号的列表赋值本身位于标量上下文中,因此其值是右侧的项目数。

答案 3 :(得分:1)

在标量上下文中使用时,列表会计算其中的项目数:

my @list = ('a', 'b', 'c');
my $list_size = @list;

进行显式测试,例如在if条件中:

my @list = ('a', 'b', 'c');
if (scalar @list == 3) {
  print "@list"; # prints list separated with spaces
}

这也可以在没有'标量'关键字的情况下使用。但是,这可能会使您的代码难以扫描。上下文是一个很好的主意,但它需要读者更多的工作。使用标量显式允许读者立即看到您在标量上下文中评估@list。

答案 4 :(得分:1)

  

如何找到值的数量   一个Perl列表?

将列表分配到@array变量,并使用@array或使用scalar(@array)操作获取$#array+1的大小。定义sub count {scalar @_}并使用对count的调用,如果你必须这么做的话。

my $n = () = ('a', 'b', 'c'); # $n = 3

当然你可以使用它...如果你希望Perl继续使用一个坏名称作为只读语言...... :(

答案 5 :(得分:1)

您也可以使用以下代码来计算数组或列表中的元素数

use strict;
use warnings;
my @array=(1,2,3,4);
my $i=0;
  foreach(@array)
  {
              $i++;
  }   
 print "The count is:$i\n";

答案 6 :(得分:-2)

为了学习数组的大小:

  1. 使用scalar()使其显式化(对于数组引用,您需要通过@{...}取消它们):

    $ perl -e '$n = scalar(qw(1 2 3)); print $n . "\n"'
    3
    
  2. 使用$#(添加加一来获取大小):

    $ perl -e '$n = [ 1, 2, 3]; print $#$n . "\n"'
    2
    $ perl -e 'print $#{[ 1, 2, 3]} . "\n"'
    2
    
  3. Perl:至少有两种方法可以做到这一点:)