如何在Perl中缩小数组?

时间:2020-03-06 14:21:30  来源:igfitidea点击:

如何在Perl中使数组更短?我阅读了一些指示可以分配的网页:

$#ARRAY = 42;

我读到不赞成使用$。我也需要一种适用于数组数组的解决方案。这不起作用:

$#$ARRAY[$i] = 42;

解决方案

$#{$ ARRAY [$ i]} = 42;

你可以做

splice @array, $length;
#or
splice @{$arrays[$i]}, $length;

选择几乎是无限的(我在这里概述了五种方法),但是策略将完全由特定需求和目标决定。 (所有示例都会将@array转换为不超过$ N个元素)

[编辑]

正如其他人指出的那样,原始问题中建议的方法实际上并没有被弃用,它提供了最快,最有趣但不一定最易读的解决方案。它还具有用空元素扩展少于$ N个元素的数组的副作用:

$#array = $N-1;

最少的代码:

#best for trimming down large arrays into small arrays
@array = $array[0..($N-1)];

从大型数组中修剪少量的最有效方法:

#This is a little less expensive and clearer
splice(@array, $n, @#array);

在几乎所有情况下都是不希望的,除非我们真的喜欢delete():

#this is the worst solution yet because it requires resizing after the delete
while($N-1 < $#array)
{
   delete(array[$i]);
}

如果我们需要按相反顺序使用列表的其余部分,则很有用:

#this is better than deleting because there is no resize
while($N-1 < $#array)
{
    pop @array;
    #or, "push $array2, pop @array;" for the reverse order remainder
}

从长远来看有助于节省时间:

#don't put more values into the array than you actually want

我不知道分配$#ARRAY已过时;来自5.10.0的perldoc perldata对此一无所知。这是截断数组的最快方法。

如果我们想让内容更具可读性,请使用splice

splice @ARRAY, 43;

(请注意,43而不是42$#ARRAY会为我们提供数组的最后一个索引,而splice`则采用数组的长度)。

至于处理数组数组,我假设意思是能够通过引用截断嵌套数组?在这种情况下,我们需要:

$#{$ARRAY->[7]} = 42;

或者

splice @{$ARRAY->[7]}, 43;

  • $#array是数组的最后一个索引。
  • $#$ array将是$ array指向的数组的最后一个索引。
  • $#$ array [$ i]表示我们要为标量建立索引-无法完成。 $#{$ array [3]}可以正确解析主数组的下标,然后再尝试引用最后一个索引。
  • 单独使用$#{$ array [3]} = 9;在$ array [3]处为自动数组分配长度9.
  • 如有疑问,请使用Data :: Dumper:
use Data::Dumper;
$#{$array[3]} = 5;
$#array       = 10;
print Dumper( \@array, $array ), "\n";

我们基本上是自己给出了规范的答案。通过设置最后一个索引来缩短数组:

$#Array = 42

绝对不建议使用$#Foo表示数组中的最后一个索引。同样,也不会弃用分配给它的内容。引用perldata文档:

The length of an array is a scalar value.  You may find the length of
  array @days by evaluating $#days, as in csh.  However, this isn’t the
  length of the array; it’s the subscript of the last element, which is a
  different value since there is ordinarily a 0th element.  Assigning to
  $#days actually changes the length of the array.  Shortening an array
  this way destroys intervening values.  Lengthening an array that was
  previously shortened does not recover values that were in those
  elements.  (It used to do so in Perl 4, but we had to break this to
  make sure destructors were called when expected.)

不建议使用$$变量,但不建议使用$$ array函数。

要在产生数组引用的任意表达式上使用$#array语法,请执行$#{EXPR}

请参阅宝贵的内容:http://perlmonks.org/?node=References+quick+reference

有两种解释问题的方法。

  • 如何减少数组的长度?
  • 如何减少阵列消耗的内存量?

到目前为止,大多数答案都集中在前者上。在我看来,对此的最佳答案是拼接功能。例如,要从末尾删除10个元素:

splice @array, -10;

但是,由于Perl如何管理数组的内存,确保数组占用较少内存的唯一方法是将其复制到新数组(并回收旧数组的内存)。为此,我倾向于考虑使用切片操作。例如,删除10个元素:

@new = @old[ 0 .. $#old - 10 ]

这是对500个元素数组(使用2104个字节)的不同方法的比较:

original: length  500 => size 2104
     pound: length  490 => size 2208
    splice: length  490 => size 2104
    delete: length  490 => size 2104
     slice: length  490 => size 2064

我们可以看到只有切片操作(复制到新数组)的大小比原始操作小。

这是我用于此分析的代码:

use strict;
use warnings;
use 5.010;
use Devel::Size qw/size/;

my @original = (1 .. 500);
show( 'original', \@original );

my @pound = @original;
$#pound = $#pound - 10;
show( 'pound', \@pound );

my @splice = @original;
splice(@splice,-10);
show( 'splice', \@splice);

my @delete = @original;
delete @delete[ -10 .. -1 ];
show( 'delete', \@delete );

my @slice = @original[0 .. $#original - 10];
show( 'slice', \@slice);

sub show {
    my ($name, $ref) = @_;
    printf( "%10s: length %4d => size %d\n", $name, scalar @$ref, size($ref));
}