【问题标题】:Referencing and printing a 2D array in Perl在 Perl 中引用和打印二维数组
【发布时间】:2016-11-17 20:48:24
【问题描述】:

我一直在阅读有关如何在 Perl 中不能拥有数组数组的文章,因此我最终在数组引用方面苦苦挣扎,我想我知道如何从子例程返回数组。但是我不能让它在返回后打印整个数组。有人可以向我解释为什么或如何调试这个问题吗?真的很感激!

#!/usr/bin/perl
use strict;
use warnings;

#Subroutine to randomize the 2D Array:
sub randPattern {
my ($rand_ref) = @_;
my @RandBoard = @$rand_ref;

for (my $i = 0; $i <= $#RandBoard; $i++) {
  for (my $j = 0; $j <= $#RandBoard ; $j++) {
     $RandBoard[$i][$j] = 0 + int(rand(3 - 0));
     print "$RandBoard[$i][$j] ";
   }
   print "\n";
  }

return @RandBoard;
}

my @checkerArr =  (
  [0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0]
);

my ($randomizedArr_ref) = randPattern(\@checkerArr); #sending arrayy as reference
my @randomizedArr = @$randomizedArr_ref; #dereferencing the returned array
print "___________________\n";

foreach (@randomizedArr){
print "$_ "; }
print "\n";

输出是这样的:

1 1 1 1 1 0 2 1 
1 0 0 0 2 2 0 1 
2 1 1 2 1 2 0 1 
1 2 0 2 0 1 0 1 
1 2 1 2 0 0 1 0 
2 1 0 1 0 0 0 2 
2 2 0 0 0 2 0 0 
1 1 1 0 0 1 1 1 
___________________
1 1 1 1 1 0 2 1 

如您所见,它只输出数组的第一行。

【问题讨论】:

    标签: arrays perl reference


    【解决方案1】:

    我认为你有点过于复杂了。

    Perl 确实做 2D 数组,你认为它的 实现 是通过引用是正确的。

    知道Data::Dumper 对于打印复杂数据结构的内容非常方便,这可能很有用。

    你的问题的核心在于这两个如何迭代:

    return @RandBoard;
    

    这会返回多个值。

    但这只会“使用”其中一个,而丢弃其余的:

    my ($randomizedArr_ref) = randPattern(\@checkerArr);
    

    所以你'捕捉'的只是对第一行的引用 - 然后打印它。如果你想尝试:

    my ( @results ) = randPattern(\@checkerArr);
    

    然后你会更接近,但我建议简单的解决方案是:

    return \@RandBoard;
    

    返回整个数据结构作为参考:

    foreach my $row ( @$randomizedArr_ref ) {
        print join " ", @$row; 
    }
    

    像这样编写代码:

    #!/usr/bin/env perl
    use strict;
    use warnings;
    
    
    #Subroutine to randomize the 2D Array:
    sub randPattern {
       my ($rand_ref) = @_;
       my @RandBoard = @$rand_ref;
    
       for ( my $i = 0; $i <= $#RandBoard; $i++ ) {
          for ( my $j = 0; $j <= $#RandBoard; $j++ ) {
             $RandBoard[$i][$j] = 0 + int( rand( 3 - 0 ) );
             print "$RandBoard[$i][$j] ";
          }
          print "\n";
       }
    
       return \@RandBoard;
    }
    
    my @checkerArr = (
       [ 0, 0, 0, 0, 0, 0, 0, 0 ],
       [ 0, 0, 0, 0, 0, 0, 0, 0 ],
       [ 0, 0, 0, 0, 0, 0, 0, 0 ],
       [ 0, 0, 0, 0, 0, 0, 0, 0 ],
       [ 0, 0, 0, 0, 0, 0, 0, 0 ],
       [ 0, 0, 0, 0, 0, 0, 0, 0 ],
       [ 0, 0, 0, 0, 0, 0, 0, 0 ],
       [ 0, 0, 0, 0, 0, 0, 0, 0 ]
    );
    
    my ($randomizedArr_ref) =
      randPattern( \@checkerArr );    #sending arrayy as reference
    
    
    print "____\n";
    foreach my $row (@$randomizedArr_ref) {
       print join " ", @$row, "\n";
    }
    

    但实际上你可以大大简化你的代码:

    foreach my $row ( @checkerArr ) { 
        $_ = int rand(3) for @$row; 
    }
    

    或者只是:

    my @checkerArr = map { 
                            [ 
                                map { int rand(3) } (1..8) #array of 8 random values
                            ] 
                         } (1..8); #8 rows. 
    

    【讨论】:

    • 您将错误留在了内部 for 循环中,他在其中循环了外部数组 $#RandBoard 的大小。
    【解决方案2】:

    首先,让我修复你的代码,然后我会解释......

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    #Subroutine to randomize the 2D Array:
    sub randPattern {
    my ($rand_ref) = $_[0];
    my @RandBoard = @$rand_ref;
    
    for (my $i = 0; $i <= $#RandBoard; $i++) {
      for (my $j = 0; $j <= $#{$RandBoard[$i]} ; $j++) {
         $RandBoard[$i][$j] = 0 + int(rand(3 - 0));
         print "$RandBoard[$i][$j] ";
       }
       print "\n";
      }
    
    return @RandBoard;
    }
    
    my @checkerArr =  (
      [0,0,0,0,0,0,0,0],
      [0,0,0,0,0,0,0,0],
      [0,0,0,0,0,0,0,0],
      [0,0,0,0,0,0,0,0],
      [0,0,0,0,0,0,0,0],
      [0,0,0,0,0,0,0,0],
      [0,0,0,0,0,0,0,0],
      [0,0,0,0,0,0,0,0]
    );
    
    my ($randomizedArr_ref) = [randPattern(\@checkerArr)]; #sending arrayy as reference
    my @randomizedArr = @$randomizedArr_ref; #dereferencing the returned array
    print "___________________\n";
    
    foreach (@randomizedArr){
        print(join(' ',@$_),"\n");
    }
    

    这里的主要问题是标量上下文与列表上下文。您正在从子例程返回一个列表,并在标量上下文 ($randomizedArr_ref) 中分配该返回的列表。你得到一个数组引用(它实际上是你的外部数组的 last 元素。你需要在列表上下文中评估方法的返回,所以我在你的方法调用周围添加了方括号(@ 987654322@).

    我还将@_ 更改为$_[0] 以更改您在子例程中设置的参数,这是一个类似的疏忽。您只获得了 whlole 参数,因为您传入了一个标量(对数组的引用)。

    哦,在你的循环中,我添加了数组的取消引用并加入了一个空格。我还将换行符移到循环中。

    更新:发现另一个我忽略的错误。在内部 for 循环中测试的内部数组的大小是使用外部数组的大小(恰好是相同的)。所以我改变了内部for循环,用$#{$RandBoard[$i]}获取内部数组的大小。

    【讨论】:

    • 此外,您实际上可以将其简化很多。出于可读性考虑,有些人可能会反对像这样使用 map,但我倾向于在更少的代码方面犯错:print(join("\n",map {join(" ",map {int(rand(3))} 1..8)} 1..8),"\n")。这几乎就是你的整个程序。您还可以使用 (0)x8 初始化一个包含 8 个 0 的数组。
    • 可能因为我错过了一些小事情而投了反对票,但我已经进行了更新以修复它们。请注意,我试图让大部分代码保持原样,这样不会有大量的更改,并且答案将集中在主要问题上。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-02
    • 2011-10-31
    • 2016-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多