【问题标题】:How to divide an array in to two different arrays in PerlPerl中如何将一个数组分成两个不同的数组
【发布时间】:2021-11-30 18:37:57
【问题描述】:

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

 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 等。

【问题讨论】:

    标签: arrays perl


    【解决方案1】:

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

    现在必须进入索引。 (好吧,或者在逐个移动/复制元素时在新数组之间交替。)一种方法

    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。

    我仍然建议通过原始帖子(如下)中链接的资源来学习如何使用这种语言的数组。


    原来的答案。更改之前的问题具有严格的两个元素的初始数组(参考),一旦将它们分成两个数组,它们(似乎)需要包装到数组参考中。这对于基本资源列表应该仍然有用(如果读者需要)。

    Perl 中的数组支持一系列操作。至于基础,我们可以从前面或后面删除和返回一个元素,shift 或pop,也可以添加unshift 或push。

    然后还有更多,包括您尝试过的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 将块中的代码应用于其输入 (@$old_array) 的每个元素,返回一个分配给 @new_array 的列表。主体中的[] 构造了一个anonymous array (reference),它是一个标量,因此可以放置在一个数组上。放置在此数组引用中的唯一元素是当前处理的 @$old_array 元素,在(普遍存在的)$_ variable 中可用。

    请参阅上面链接的perlintro 和perldata,以及shift 中的链接。有关库中提供的列表和数组的许多其他操作,请参阅List::Util 和List::MoreUtils 了解初学者。

    有关引用,请参阅 perlreftut,有关具有引用的数组,请参阅 perllol(列表的列表)和 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;
    

    打印出来(为了这篇文章的可读性,只是压缩了)

    $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 ];
    

    【讨论】:

    • 其实按照这个逻辑,数组并没有一分为二。
    • @KamakshiTrivedi 您可以将您的代码添加到您的问题中吗? (并阐明您期望的确切输出——一个包含两个数组引用的数组,或两个单独的数组。)我在此处发布的小代码 sn-ps 工作正常。我正在添加一个完整的程序,用于复制粘贴...
    • @KamakshiTrivedi 我想我明白你的问题是什么——你有一个数组 reference 开始,而不是数组。这是一个非常小的调整,我已经调整了帖子。
    • (我的意思是你有这个答案的问题。否则它在任何意义上都不是问题,有一个数组引用而不是一个数组。)跨度>
    • 我已经编辑了问题,你可以看看。
    【解决方案2】:

    你基本上得到了正确的答案。你原来有

    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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-20
      • 2019-05-03
      • 1970-01-01
      • 1970-01-01
      • 2023-01-17
      • 2022-01-24
      • 2020-03-29
      • 1970-01-01
      相关资源
      最近更新 更多