首页 > 解决方案 > 在 perl 中,如何提取一个已经存在于数组数组中的子数组?

问题描述

@BIG是一个数组数组。它具有子数组 0、子数组 1 等。我想选择任何子数组,仅通过其索引指定它,并将其确切值(包括其结构)复制或分配给my @extracted_subarray,而不更改@BIG

下面的代码创建并打印了一个@BIG. 然后最后一行,使用pop,设法将第二个(索引 1)子数组的值分配给my @extracted_subarray。这不是我想要的,因为

  1. 它只获取 的最后一个子数组@BIG,而我想通过其索引指定任意现有子数组。
  2. 它从 中删除子数组@BIG,而我想保持@BIG不受干扰。

当然,必须有一种直接的方法来做到这一点。因为我在R( r-project.org ) 中编写了很多代码,所以我认为这是一项非常基本的任务。但是“从数组数组中提取子数组”似乎不是正确的搜索词。它为比这个更复杂的问题提供了解决方案。

里面的两个块{...} 在一些阅读这篇文章的人中提出了问题。因此,一个解释。我的实际应用程序不会有这样的硬编码数据元素。我将遍历一个文本文件,其中包含数组各个元素的单独行,并从文本文件构建数组。

特别是,以 开头的@行将表示一个新的子数组。后面的字符串@将是@atsign子子数组中的唯一元素。在此行之后将出现以 开头的任意数量的行=,它们将成为 @EQsign 子子数组的元素。因此,在实际代码中,每次遇到类似@hrdl:raw_:in:__:. 并且在每一行一样=\.(((tex)|(txt))|((TEX)|(TXT))),另一个元素将被推入@EQsign

但前两段与我的问题无关。我的问题是如何提取对应于从 0 到(scalar @BIG) -1). 例如,如果我指定索引 1,我希望@extracted_subarray内容和结构与@tmparray在迭代 1 中构建的内容和结构相同。在下面的示例中,这意味着@tmparray存在于第二个块中的 。

我想要@extracted_subarray并且@BIG彼此独立存在。两者都不应该仅仅是一个指针或对另一个的引用。因此,如果随后更改@tmparray@BIG更改,我希望其他数组不受影响。

#!/usr/bin/perl
use strict; use warnings;
use Data::Dumper qw(Dumper); #https://perlmaven.com/hash-of-arrays
select(STDERR);

my @BIG;

{
    my @tmparray;
    my @atsign;
    my @EQsign;
    push @atsign, 'hrdl:raw_:in:__:';
    push @EQsign, ( '\.(((tex)|(txt))|((TEX)|(TXT)))' );
    push @tmparray, [@atsign];
    push @tmparray, [@EQsign];
    push @BIG, [@tmparray];
}

{
    my @tmparray;
    my @atsign;
    my @EQsign;
    push @atsign, 'hrdl:raw_:EX:__:i';
    push @EQsign, ( 'bad words', 'bad\s*word' );
    push @EQsign, ( 'forbidden', );
    push @tmparray, [@atsign];
    push @tmparray, [@EQsign];
    push @BIG, [@tmparray];
}
print "BIG=\n"; print Dumper \@BIG;
my @extracted_subarray;
@extracted_subarray = pop @BIG;
print "extracted_subarray=\n"; print Dumper \@extracted_subarray;

标签: arraysperl

解决方案


@BIG包含对数组的引用。您可以获得以下参考资料之一:

my $sub_array = $BIG[0];

然后,您可以执行for (@$sub_array),$sub_array->[0]等操作。请参阅perlreftut


请记住,这$BIG[0]只是对数组的引用,因为您不能将数组放入数组中。要复制参考数组,您可以使用

my @shallow_copy_of_sub_array = @{ $BIG[0] };

您是否会复制$BIG[0]( @tmparray) 引用的数组,该数组也是引用的元素,因此@shallow_copy_of_sub_array并不@BIG完全独立。例如,更改$shallow_copy_of_sub_array[0][0]将影响@BIG. 为了解决这个问题,我们可以使用

my $copy = [
   [ $BIG[0][0] ],
   [ $BIG[0][1] ],
];

或者我们可以一直复制所有引用的变量。这称为制作深拷贝。

use Storable qw( dclone );

my $deep_copy = dclone($BIG[0]);

或者

use Cpanel::JSON::XS qw( encode_json decode_json );

my $deep_copy = decode_json(encode_json($BIG[0]));

顺便一提,

{
    my @tmparray;
    my @atsign;
    my @EQsign;
    push @atsign, 'hrdl:raw_:in:__:';
    push @EQsign, ( '\.(((tex)|(txt))|((TEX)|(TXT)))' );
    push @tmparray, [@atsign];
    push @tmparray, [@EQsign];
    push @BIG, [@tmparray];
}

很浪费。您正在免费制作数组的副本。([ @atsign ]或多或少等同于my @anon = @atsign; \@anon。) 固定:

{
    my @tmparray;
    my @atsign;
    my @EQsign;
    push @atsign, 'hrdl:raw_:in:__:';
    push @EQsign, ( '\.(((tex)|(txt))|((TEX)|(TXT)))' );
    push @tmparray, \@atsign;
    push @tmparray, \@EQsign;
    push @BIG, \@tmparray;
}

它仍然是不必要的冗长,妨碍了可读性。固定的:

{
    my @atsign = 'hrdl:raw_:in:__:';
    my @EQsign = ( '\.(((tex)|(txt))|((TEX)|(TXT)))' );
    push @BIG, [ \@atsign, \@EQsign ];
}

你甚至可以使用

push @BIG, [
    [ 'hrdl:raw_:in:__:' ],
    [ '\.(((tex)|(txt))|((TEX)|(TXT)))' ],
];

这样就清楚多了。


推荐阅读