Perl将项推入子数组

9vw9lbht  于 2022-11-15  发布在  Perl
关注(0)|答案(3)|浏览(189)

我有2个空数组,我使用for循环向其中添加项。

@main = (
    "a 1 b 2 c 3 ",
    "d 4",
    "e 5 f 6 g 7 h 8",
    "i 9 j 10",
);
@arr1 = (); #only gets the letters
#supposed to look like:
#( 
#[a,b,c]
#[d]
#[e,f,g,h]
#[i,j]
#)

@arr2 = (); #only gets the numbers
#supposed to look like:
#( 
#[1,2,3]
#[4]
#[5,6,7,8]
#[9,10]
#)
for($i=0;@main;$i+=1){
    @line = split(/\s+/,shift(@main));
    push(@arr1,[]);
    push(@arr2,[]);
    while(@line){
        push(@arr1[$i],shift(@line));
        push(@arr2[$i],shift(@line));
    }
}

错误:

Experimental push on scalar is now forbidden at index.pl line 29, near "))"
Experimental push on scalar is now forbidden at index.pl line 30, near "))"

看起来@arr[$i]返回了一个数组的引用。我该如何得到这个数组并向其中添加项?

bcs8qyzn

bcs8qyzn1#

push的第一个参数必须是一个数组,而不是数组切片。我想你想要的是@{ $arr1[$i] }(但这不是你唯一的问题)。确保你使用的是use strict;使用警告;!-池上

for(my $i=0;@main;$i+=1){
    my @line = split(/\s+/,shift(@main));
    push(@arr1,[]);
    push(@arr2,[]);
    while(@line){
#             ↓↓           ↓ 
        push( @{ $arr1[$i] } ,shift(@line));
        push( @{ $arr2[$i] } ,shift(@line));
    }
}

不太清楚它是如何工作的,可能会把引用变成一个实际的数组。
我自己想到的另一个解决方案是,在完成数组后添加数组,而不是缓慢地添加值:

for($i=0;@main;$i+=1){
    @line = split(/\s+/,shift(@main));
    @subArr1 = ();
    @subArr2 = ();
    while(@line){
        push(@subArr1,shift(@line));
        push(@subArr2,shift(@line));
    }
    push(@arr1,[@subArr1]);
    push(@arr2,[@subArr2]);
}
eyh26e7m

eyh26e7m2#

从perl5.36开始,您可以在foreach循环中一次迭代列表的多个元素,这让您可以稍微清理一下:

#!/usr/bin/env perl
use 5.036;
# The next two lines aren't strictly needed because of the above, but
# I like to be explicit
use strict;
use warnings;
use experimental qw/for_list/;
use Data::Dumper;

my @main = (
    "a 1 b 2 c 3 ",
    "d 4",
    "e 5 f 6 g 7 h 8",
    "i 9 j 10",
    );
my (@arr1, @arr2);

for my $line (@main) {
    my (@sub1, @sub2);
    for my ($name, $num) (split " ", $line) {
        push @sub1, $name;
        push @sub2, $num;
    }
    push @arr1, \@sub1;
    push @arr2, \@sub2;
}

print Dumper(\@arr1, \@arr2);

您可以在旧版本中使用List::MoreUtils module中的natatime(可从CPAN或操作系统的软件包管理器获得)使用相同的方法:

#!/usr/bin/env perl
use strict;
use warnings;
use List::MoreUtils qw/natatime/;
use Data::Dumper;

my @main = (
    "a 1 b 2 c 3 ",
    "d 4",
    "e 5 f 6 g 7 h 8",
    "i 9 j 10",
    );
my (@arr1, @arr2);

for my $line (@main) {
    my (@sub1, @sub2);
    my $it = natatime 2, split(" ", $line);
    while (my ($name, $num) = $it->()) {
        push @sub1, $name;
        push @sub2, $num;
    }
    push @arr1, \@sub1;
    push @arr2, \@sub2;
}

print Dumper(\@arr1, \@arr2);

它们的共同点是首先构建每个子数组,然后将对它们的引用推送到@arr1@arr2上,这样就不需要大量的arrayref解引用语法,它们还可以直接迭代存储在子数组中的元素,而不是直接用shift修改源代码。

nle07wnf

nle07wnf3#

请检查下列示范程式码是否符合您的问题。
该代码基于OP代码中的注解,并描述了结果数组应该是什么样的。

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my(@main,@arr1,@arr2);

@main = (
    "a 1 b 2 c 3 ",
    "d 4",
    "e 5 f 6 g 7 h 8",
    "i 9 j 10",
);

for ( @main ) {
    push(@arr1,[ /(\d+)/g   ]);
    push(@arr2,[ /([a-z])/g ]);
}

say Dumper(\@arr1,\@arr2);

输出量

$VAR1 = [
          [
            '1',
            '2',
            '3'
          ],
          [
            '4'
          ],
          [
            '5',
            '6',
            '7',
            '8'
          ],
          [
            '9',
            '10'
          ]
        ];

$VAR1 = [
          [
            'a',
            'b',
            'c'
          ],
          [
            'd'
          ],
          [
            'e',
            'f',
            'g',
            'h'
          ],
          [
            'i',
            'j'
          ]
        ];

相关问题