如何在 Perl 中将一个数组分成两个不同的数组

How to divide an array in to two different arrays in Perl

我有一个哈希数组,我需要将它分成两个不同的数组。哈希数组如下所示:

 old_array = [
   {
      'a'=>1,
      'b'=>2,
      'c'=>3,
      'd'=>4
   },
   {  
      'e'=>5,
      'f'=>6,
      'g'=>7,
      'h'=>8
   },
  {  
      'i'=>9,
      'j'=>10,
      'k'=>11,
      'l'=>12
   },
  {  
      'm'=>13,
      'n'=>14,
      'o'=>15,
      'p'=>16
   }

];

我需要按照以下方式将它分成两个不同的数组:

   new_array_1 = [{
      'a'=>1,
      'b'=>2,
      'c'=>3,
      'd'=>4
   },
   {  
      'e'=>5,
      'f'=>6,
      'g'=>7,
      'h'=>8
   }
 ];


 new_array_2 = [{  
      'i'=>9,
      'j'=>10,
      'k'=>11,
      'l'=>12
   },
  {  
      'm'=>13,
      'n'=>14,
      'o'=>15,
      'p'=>16
   }
 ];

我现在已经尝试了其中一个答案中提到的以下代码:

     my ($new_array_1, $new_array_2) =
    map { [ $_ ] }
          @$old_array;

这是拆分数组但删除了中间的哈希值,我得到的输出为:

   $VAR1 = [
      {
        'c' => 3,
        'a' => 1,
        'b' => 2,
        'd' => 4
      }
    ];

$VAR1 = [
      {
        'g' => 7,
        'f' => 6,
        'e' => 5,
        'h' => 8
      }
    ];

我应该怎么做才能得到想要的输出?哈希可能会增加到 10 或 20 或 15 等

问题发生了重大变化,现在 arrayref 不再有两个元素,而是更多,它需要拆分,以便它的两半进入两个数组。元素不需要做成 arrayrefs.

现在必须去索引。 (好吧,或者在 moving/copying 逐个元素的同时在新数组之间交替。)一种方式

my $midind = ($#$old_arrayref-1)/2;  # or: (@$oldarrayref/2)-1

my $new_arrayref_1 = [ @$old_arrayref[0..$midind] ];
my $new_arrayref_2 = [ @$old_arrayref[$midind+1 .. $#$old_array] ];

这会保留原来的数组。 (语法 $#$arrayref 用于数组引用 $arrayref 中的最后一个索引。)如果旧数组无关紧要,可以改为

my $new_arrayref_1 = [ splice @$old_arrayref, 0, $midind+1 ];
my $new_arrayref_2 = [ @$old_arrayref ];

注意 如果原始数组的元素本身包含复杂的数据结构(因此,引用),那么它们需要被“深度复制”,例如使用 Storable::dclone .

我仍然建议阅读原始 post(下方)中链接的资源,以了解如何使用这种语言使用数组。


原答案。更改之前的问题是初始数组 (ref) 严格包含两个元素,一旦将它们拆分为两个数组,它们(表面上)需要包装到 arrayrefs 中。这对于基本资源列表应该仍然有用(如果 reader 需要)。

Perl 支持对数组的一系列操作。至于基础,我们可以从前面或后面删除和 return 一个元素,用 shiftpop,可以用 unshiftpush 添加。

然后还有更多,包括splice你试过的,还有更复杂操作的库。但是基础知识很容易解决您的问题。一种方式

my $old_arrayref = [ { a=>1, b=>2 }, { c=>3, d=>4 } ];

my @new_array_1 = shift @$old_array;
my @new_array_2 = shift @$old_array;

(一个 array 可以简单地分配一个元素列表,包括一个元素。但是如果数组中有任何东西,那么在这样的分配之后它就会全部消失所以不要忘记这一点。 )

在这里,我将源 (old_array) 作为数组引用,紧接着问题。现在 $old_array 是空的,如果它只有那两个元素,它们现在在 @new_array_N 中。

另一种更基本的方法是 index into the array 访问单个元素并将它们复制到新数组。这样 $old_array 就会保持原样。

也许更合理的安排是将这两个新数组的引用作为数组的元素,这可能是您的代码试图做的。为此,您只需要

my @new_array = map { [ $_ ] } @$old_array;

map applies the code in the block to each element of its input (@$old_array), returning a list, assigned to @new_array. That [] in the body constructs an anonymous array (reference), which is a scalar and as such can be placed on an array. The only element placed in this array-reference is the currently processed element of @$old_array, available in the (ubiquitous) $_ variable.

参见上面的 perlintroperldata 链接,以及 shift 中的链接。对于库中提供的列表和数组的许多其他操作,请参阅 List::Util and List::MoreUtils 初学者。

有关参考资料,请参阅 perlreftut and for arrays with references see perllol (lists-of-lists) and perldsc(数据结构指南)。

一个完整的程序

use warnings;
use strict;
use feature 'say';
use Data::Dumper;

my @old_array = ( { 'a'=>1, 'b'=>2 }, { 'c'=>3, 'd'=>4 } );  

my @new_array = map { [ $_ ] } @old_array;

say Dumper \@new_array;

这会打印出来(只是压缩,以便于阅读 post)

$VAR1 = [
          [ { 'a' => 1, 'b' => 2 } ],
          [ { 'c' => 3, 'd' => 4 } ]
        ];

如果新数组也需要数组引用

my $new_arrayref_1 = [ shift @$old_array ];
my $new_arrayref_2 = [ shift @$old_array ];

在第二个例子和简短的“完整程序”中

my $new_arrayref = [ map { [ $_ ] } @$old_array ];

你基本上答对了。你原来有

my @new_array;
push @new_array, [ splice @$missingSections, 0, 2 ] while @$old_array;

应该是

my @new_array;
push @new_array, [ splice @$old_array, 0, 2 ] while @$old_array;

也可以这样写:

use List::MoreUtils qw( natatime );

my @new_array;
my $iter = natatime 2, @$old_array;
while ( my @vals = $iter->() ) {
   push @new_array, \@vals;
}
my @new_array =
   map [ $old_array->@[ $_*2+0, $_*2+1 ] ],
      0..@$old_array/2;
use List::Util qw( pairs );

my @new_array = pairs @$old_array;
use List::MoreUtils qw( part );

my @new_array = part { $_/2 } 0..$#$old_array;