【问题标题】:Perl: Iterating through this funky array?Perl:遍历这个时髦的数组?
【发布时间】:2011-04-11 21:09:30
【问题描述】:

我正在尝试迭代以这种特定方式构造的二维数组。这是否是构造数组的好方法是另一个问题 - 我仍然需要能够迭代它(如果可能的话)。

@row1 = ( "Current Scan", "Last Month");
@row2 = ( "240", "0");
@row3 = ( "226", "209");
@row4 = ( "215", "207");

@array = (\@row1, \@row2, \@row3, \@row4);
print Dumper(@array);
printarray(@array);

Dumper 给了我以下输出:

$VAR1 = [
          'Current Scan',
          'Last Month'
        ];
$VAR2 = [
          '240',
          '0'
        ];
$VAR3 = [
          '226',
          '209'
        ];
$VAR4 = [
          '215',
          '207'
        ];

我已经尝试了几个 for 循环,但都没有成功。每个只打印第一行 ($VAR1) 并退出。这是我最近的尝试:

sub printarray {
  @array = shift;
  $rowi = 0;
  foreach my $row (@array) {
    for (my $coli = 0; $coli <= @$row; $coli++) {
      print "$array[$rowi][$coli]\n";
    }
    $rowi++;
  }
}

我显然忽略了一些简单的事情。我究竟做错了什么?提前致谢!

【问题讨论】:

  • 不确定您期望得到什么结果,但使用length 函数时出现错误。您不需要它,因为它返回字符串的长度。使用$coli &lt; @$row 作为循环条件。
  • 谢谢,我已经对其进行了编辑,希望能更清楚一点。我基本上只是想遍历整个数组,由于某种原因它只遍历第一行。
  • 我认为我遗漏了一个非常重要的部分。起初我以为只是我搞砸了迭代,但我忘记了我正在通过一个子程序传递它......我猜这就是问题......
  • 您使用的数据转储程序错误。请记住,Perl 将函数参数中的数组扩展为列表,因此如果您想要转储顶级数组,则需要使用 print Dumper \@array; 而不是您所拥有的。 Perl 的列表扩展使普通函数调用类似于使用 APPLY 函数调用的 Lisp 函数。请参阅en.wikipedia.org/wiki/Apply 了解更多信息。
  • 另外,请参阅 perldoc 中的 perllol 和 perldsc,了解使用常见数据结构的示例。见perldoc.perl.org/perllol.htmlperldoc.perl.org/perldsc.html

标签: arrays perl multidimensional-array


【解决方案1】:

如果您只想打印数组,请尝试以下代码:

foreach my $row (@array) {
   foreach my $elem (@$row) {
       print $elem; ## print elements without separator
   }
   print "\n"; ## new line after row
}

如果您出于某种目的需要索引,我们可以这样做:

for(my $row_i = 0; $row_i < @array; $row_i++) {
    for(my $column_i = 0; $column_i < @{ $array[$row_i] }; $column_i++) {
        print $array[$row_i][$column_i];
    }
}

这个想法是 标量上下文 中的@array 返回数组中元素的数量。而@{ $array[$row_i] } 有点棘手。它取消引用存储在$array[$row_i] 中的数组。

子程序更新:

在 perl 中你可以通过引用传递数组:

 printarray(\@array); ## pass reference

 sub printarray {
     my $array_ref = shift; ## no copy created

     foreach my $row (@$array_ref) { ## now we need to dereference
         ...
     }
 }

你也可以传递数组的副本:

 printarray(@array);

 sub printarray {
     my @array_copy = @_; ## store local copy of array
     ...
 }

有关更多详细信息,请查看How can I pass/return a {Function, FileHandle, Array, Hash, Method, Regex}? 手册页。

请在程序开头加上use strict;。它会强制你声明所有变量,但如果你输入错误会节省大量时间。

【讨论】:

  • 谢谢。我在上面遗漏了一个更重要的部分。我太专注于迭代部分,以至于忘记了我已经通过子程序传递了它……我认为这就是问题所在。
【解决方案2】:

当您将数组传递给子例程时,您实际上是在传递八个标量。然后,当你这样做时

sub printarray {
  @array = shift;

...您只弹出列表中的第一个元素。试试:

sub printarray {
  @array = @_;

【讨论】:

    【解决方案3】:
    #!/usr/bin/perl 使用警告; 使用严格; 我的@row1 =(“当前扫描”,“上个月”); 我的@row2 = ("240", "0"); 我的@row3 = ("226", "209"); 我的@row4 =(“215”,“207”); 我的@array = (\@row1, \@row2, \@row3, \@row4); foreach 我的 $row (@array) { foreach 我的 $value (@$row) { 打印“$值\n”; } }

    这将打印出来

    当前扫描 上个月 240 0 226 209 215 207

    不确定这是不是你想要的。

    【讨论】:

      【解决方案4】:

      是的,问题在于您将数组传递给子例程的方式。 Perl 将参数列表中的数组展平。基本上,printarray(@array)(在本例中)等价于printarray($array[0], $array[1], $array[2], $array[3])printarray开头的shift取第一个参数,赋值给@array。所以无论数组有多大,printarray 只能看到第一个元素。

      【讨论】:

        【解决方案5】:

        您是否正在寻找这样的东西:

        #!/usr/bin/perl
        use warnings;
        use strict;
        use Algorithm::Loops 'MapCar';
        
        my @row1 = ( "Current Scan", "Last Month");
        my @row2 = ( "240", "0");
        my @row3 = ( "226", "209");
        my @row4 = ( "215", "207");
        
        my @array = (\@row1, \@row2, \@row3, \@row4);
        
        MapCar { print "Scan: $_[0]: $_[1], $_[2], $_[3]\n" } @array;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-11-26
          • 2012-08-25
          • 2021-12-06
          • 2013-12-11
          • 1970-01-01
          • 1970-01-01
          • 2011-12-18
          • 2015-11-21
          相关资源
          最近更新 更多