我可以在Perl中将数组初始化为给定大小吗?

我可以在Perl中将数组初始化为给定大小吗?,perl,Perl,我的代码中有一个部分,我知道我需要一个数组,我确切地知道这个数组需要多少元素。这段代码会重复很多次,因此我可以通过首先将数组初始化到我知道它需要的大小,然后填充它来节省大量时间,而不是仅仅推送项(推送将是O(n),而不是填充已经创建的空间,即O(1)) 也就是说,我似乎找不到任何优雅的方法将数组初始化为给定的大小,我也不知道为什么。我知道我能做到: my@array$数组[49]=0 为了得到一个50个项目的数组,但这看起来真的很难看,我觉得好像有更好的方法。想法?老实说,您的方式非常好,因为它

我的代码中有一个部分,我知道我需要一个数组,我确切地知道这个数组需要多少元素。这段代码会重复很多次,因此我可以通过首先将数组初始化到我知道它需要的大小,然后填充它来节省大量时间,而不是仅仅推送项(推送将是O(n),而不是填充已经创建的空间,即O(1))

也就是说,我似乎找不到任何优雅的方法将数组初始化为给定的大小,我也不知道为什么。我知道我能做到:

my@array$数组[49]=0


为了得到一个50个项目的数组,但这看起来真的很难看,我觉得好像有更好的方法。想法?

老实说,您的方式非常好,因为它明确地改变了数组的大小:
$\array=49

你的方式很好,DVK的也很好。在单个命令中执行此操作的方法可能是:

@array = (0 .. 49);

但我不确定它是否更优雅,因为它为每个元素指定了一个介于1和49之间的值,但对于程序员来说,理解Perl语法可能更直观。

每当您考虑进行这种类型的优化时,请进行一些分析!结果可能不是你所期望的。例如,我使用以下快速脚本测试您的理论,即预分配阵列更快:

for ( my $loops = 0; $loops < 100000; $loops++ )
{
    my @arr;

    for ( my $foo = 0; $foo < 50; $foo++ ) {
        push @arr, 'bar';
    }
}
for(我的$loops=0;$loops<100000;$loops++)
{
我的@arr;
对于(我的$foo=0;$foo<50;$foo++){
按“arr”键,“bar”;
}
}
这花了2.13秒

for ( my $loops = 0; $loops < 100000; $loops++ )
{
    my @arr;
    $arr[49] = 0;

    for ( my $foo = 0; $foo < 50; $foo++ ) {
        $arr[$foo] = 'bar';
    }
}
for(我的$loops=0;$loops<100000;$loops++)
{
我的@arr;
$arr[49]=0;
对于(我的$foo=0;$foo<50;$foo++){
$arr[$foo]=“bar”;
}
}
这花费了2.16秒(我多次运行这两个测试)。因此,实际上,让perl根据需要处理分配数组会更快

更新

在做出ysth建议的更改后,这些数字更有意义:“推送”方法为2.27秒,预分配为2.21秒。即便如此,我还是会质疑这样的优化是否真的能节省时间(100000次迭代后的差异仅为0.06秒)

  • 优化俱乐部的第一条规则是,你不优化
  • 优化俱乐部的第二条规则是,你需要 没有测量就没有优化

  • 测量,测量,在您离开之前测量,并假设您可以通过伪造Perl更快地完成它。Perl对常用用法进行优化的时间比您长得多。信任它。

    使用undef而不是特定值

    my @array;
    $array[49] = undef;
    

    预分配可能对速度没有多大帮助,但如果分配的块足够大,它可能有助于将内存返回到系统

    预分配数组没有问题,但这听起来像是过早的微观优化。为什么你认为推送是O(n)?现在没有时间找到链接,但长话短说:推送需要在数组中循环找到最后一个开放空间(无论如何,这是推送通常的实现方式,尽管现在我在考虑它,这是针对单链接列表而不是通常的数组)。你是说它在Perl中的实现不同吗?是的,有点不同。Perl列表是前后都有些松弛的数组。它们也知道自己的大小,因此推送和取消移动通常都是O(1)。如果空闲时间用完了,Perl将重新分配一个具有更多空间的新数组。重新分配是一个O(n)操作,但它只需要在每次~log(n)推送操作后发生。另请参见:好奇,Eli,你的编程背景是什么?@arr在一次迭代到下一次迭代中重复使用;要强制它不被重用,请说
    my$arrref在外循环之前,并且
    $arrref=\@arr在外循环的末尾。更新了我的答案以反映ysth的建议。我想这是一个获得更客观结果的好方法,但在现实世界中会做这样的事情吗?-1你的方法不好。。。您没有预先分配,您只需在一行中设置50个值@塞伯特,我就是这么说的。请阅读代码下面的部分。从0到49?如果元素也需要初始化,请使用
    my@array=(0)x50