【问题标题】:How can I iterate through nested arrays?如何遍历嵌套数组?
【发布时间】:2010-12-06 23:44:23
【问题描述】:

我已经创建了一个数组如下

while (defined ($line = `<STDIN>`))

        {
        chomp ($line);
        push @stack,($line);
        }

每行有两个数字。

15 6
2  8

如何遍历每一行中的每一项?

即我要打印

15
6
2
8

我知道是这样的

foreach (@{stack}) (@stack){

    print "?????
}  

这就是我卡住的地方。

【问题讨论】:

  • 不明白您想要打印的内容与已有的内容有何不同。此外,这些反引号看起来也不对。
  • 后面的同上。删除它们并使用while (my $line = &lt;&gt;)
  • while(my $line=&lt;&gt;) 自动转换为 while(defined(my $line=&lt;&gt;))

标签: perl arrays loops


【解决方案1】:

请参阅perldsc 文档。那是 Perl Data Structures Cookbook,其中包含处理数组数组的示例。不过,从您正在做的事情来看,您似乎不需要数组数组。

对于每行取两个数字并每行输出一个数字的问题,只需将空格转换为换行符:

 while( <> ) {
     s/\s+/\n/; # turn all whitespace runs into newlines
     print;     # it's ready to print
     }

在 Perl 5.10 中,您可以使用仅匹配水平空格的新 \h 字符类:

 while( <> ) {
     s/\h+/\n/; # turn all horizontal whitespace runs into newlines
     print;     # it's ready to print
     }

作为 Perl 单行代码,这只是:

 % perl -pe 's/\h+/\n/' file.txt

【讨论】:

    【解决方案2】:
    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    while ( my $data = <DATA> ) {
        my @values = split ' ', $data;
        print $_, "\n" for @values;
    }
    
    
    __DATA__
    15 6
    2  8
    

    输出:

    C:\温度> h 15 6 2 8

    或者,如果您想将每一行存储在@stack 中并稍后打印出来:

    my @stack = map { [ split ] } grep { chomp; length } <DATA>;
    

    上面的行将来自DATA 文件句柄的所有内容都插入到行列表中(因为&lt;DATA&gt; 发生在列表上下文中)。 grep chomping 每一行并在 chomping 后按长度过滤(以避免在数据文件中出现任何尾随空行——如果没有空行,您可以避免它)。 map 然后沿空格分割每一行,然后为每一行创建一个匿名数组引用。最后,这样的数组引用存储在@stack 的每个元素中。您可能想使用Data::Dumper 查看@stack 以了解发生了什么。

    print join("\n", @$_), "\n" for @stack;
    

    现在,我们查看堆栈中的每个条目,依次解引用每个数组,然后用换行符连接每个数组的元素,以每行打印一个元素。

    输出:

    C:\温度> h 15 6 2 8

    编写基本相同的东西(内存消耗更少)的漫长方法是:

    my @stack;
    
    while ( my $line = <DATA> ) {
        last unless $line =~ /\S/;
        my @values = split ' ', $line;
        push @stack, \@values;
    }
    
    for my $ref ( @stack ) {
        print join("\n", @$ref), "\n";
    }
    

    最后,如果您想要做的不是打印所有值,比如对所有数字求和,您应该为@stack 的每个元素存储一个值:

    use List::Util qw( sum );
    
    my @stack;
    
    while ( my $line = <DATA> ) {
        last unless $line =~ /\S/;
        my @values = split ' ', $line;
        push @stack, @values;
    }
    
    printf "The sum is %d\n", sum @stack;
    

    【讨论】:

      【解决方案3】:
      #!/usr/bin/perl
      
      while ($line = <STDIN>) {
          chomp ($line);
          push @stack, $line;
      }
      
      # prints each line
      foreach $line (@stack) {
          print "$line\n";
      }
      
      # splits each line into items using ' ' as separator
      # and prints the items
      foreach $line (@stack) {
          @items = split / /, $line;
      
          foreach $item (@items) {
              print $item . "\n";
          }
      }
      

      【讨论】:

      • 最后的“for”是否也需要是“foreach”?
      • Foreach 肯定会更容易理解,来自 perldoc perlsyn: >“foreach”关键字实际上是“for”关键字的同义词,因此您可以使用“foreach”来提高可读性或为简洁起见。
      • foreachfor 行为相同。许多 perlers 更喜欢专门使用for
      • 我曾经是 foreach 的忠实粉丝。现在我已经忘记了它甚至存在。 (或者也许我只是“为了”它甚至存在......)
      • 怎么办?你的代码就是我所做的,只是做更多的工作。甚至没有人在任何代码中显示单个引用。
      【解决方案4】:

      我将“for”用于“C”样式循环,将“foreach”用于迭代列表。

      【讨论】:

      • 没有必要人为的对两者做这样的区分。
      • 没有必要,但我也是这样做的。这只是语法糖。
      • 我两者都使用for。 C 风格的循环将在 Perl6 中使用 loop 编写,foreach 将重命名为 for
      【解决方案5】:
      #!/usr/bin/perl
      
      use strict;
      use warnings;
      open IN, "< read.txt" or
          die "Can't read in 'read.txt'!";
      
      my $content = join '', <IN>;
      
      while ($content =~ m`(\d+)`g) {
          print "$1\n";
      }
      

      【讨论】:

        猜你喜欢
        • 2021-08-18
        • 1970-01-01
        • 2021-06-16
        • 2017-05-13
        • 2017-09-08
        • 1970-01-01
        • 2019-03-20
        • 1970-01-01
        • 2018-07-12
        相关资源
        最近更新 更多