【问题标题】:How can I print N array elements with delimiters per line?如何打印每行带有分隔符的 N 个数组元素?
【发布时间】:2012-03-16 00:41:27
【问题描述】:

我在 Perl 中有一个数组,我想在每个元素之间使用空格分隔符打印,除了应该换行分隔的每 10 个元素。如果重要的话,元素中没有任何空格。

我已经编写了一个函数来使用 for 和一个计数器,但我想知道是否有更好/更短/规范的 Perl 方式,也许是特殊的连接语法或类似的。

我的功能来说明:

sub PrintArrayWithNewlines
{
    my $counter = 0;
    my $newlineIndex = shift @_;

    foreach my $item (@_)
    {
        ++$counter;
        print "$item";
        if($counter == $newlineIndex)
        {
            $counter = 0;
            print "\n";
        }
        else
        {
            print " ";
        }
    }
}

【问题讨论】:

    标签: perl


    【解决方案1】:

    我喜欢splice 这样的工作:

    sub PrintArrayWithNewlines {
        my $n = 10;
        my $delim = " ";
        while (my @x = splice @_, 0, $n) {
            print join($delim, @x), "\n";
        }
    }
    

    【讨论】:

      【解决方案2】:

      你可以使用List::MoreUtils::natatime:

      use warnings; use strict;
      
      use List::MoreUtils qw( natatime );
      
      my @x = (1 .. 35);
      
      my $it = natatime 10, @x;
      
      while ( my @v = $it->() ) {
          print "@v\n"
      }
      

      输出:

      C:\Temp> x
      1 2 3 4 5 6 7 8 9 10
      11 12 13 14 15 16 17 18 19 20
      21 22 23 24 25 26 27 28 29 30
      31 32 33 34 35

      【讨论】:

      • natatime 真的很酷。我只是希望我没有把它读成“nata time”。娜塔!
      【解决方案3】:

      如果不想使用任何外部模块,可以使用数组切片:

      use warnings; use strict;
      
      my @x = (1 .. 95);
      my $n = 10;
      
      for my $i ( 0 .. int @x/$n ) {
          no warnings 'uninitialized';
          print "@x[$n * $i .. $n * ($i + 1) - 1]\n";
      }
      

      【讨论】:

      • 而且,当你想改变分隔符时,只需设置 $"
      • 这对数组是非破坏性的,因此,IMO 比 splice 更可取,因为您可以将它与数组引用一起使用。我会使用natatime,除非由于某种原因我无法使用 List::MoreUtils。
      【解决方案4】:

      我的模块List::Gen中的函数byevery可以解决这个问题:

      use List::Gen;
      
      for (every 10 => 'a' .. 'z') {
          print "@$_\n"
      }
      
      #   a b c d e f g h i j
      #   k l m n o p q r s t
      #   u v w x y z
      

      也可以写

      foreach (by 10 => 'a' .. 'z') {
          print "@$_\n"
      }
      

      或使用函数形式:

      mapn {print "@_\n"} 10 => 'a' .. 'z';  # @_ not @$_ here
      

      如果这是你的风格,也可以是迭代器:

      my $letters = by 10 => 'a' .. 'z';
      
      while (my $line = $letters->next) {
         print "@$line\n";
      }
      

      【讨论】:

        【解决方案5】:

        您也可以使用map 修改为PrintArrayWithNewlines

        #!/usr/bin/perl -w
        
        use strict;
        
        sub PrintArrayWithNewlines 
        {    
            my @array = @_;
            my $newlineIndex = 10;
        
            foreach my $item (@array) {
                ++$globalCounter;
                print "$item";
                if ($globalCounter == $newlineIndex) {
                    $globalCounter = 0;
                    print "\n";
                }
                else {
                    print " ";
                }
            }
        }
        
        my $globalCounter = 0;
        my @myArray = 'a' .. 'z'
        map { PrintArrayWithNewlines($_) } @myArray;
        print "\n";
        

        输出将是:

        $ ./test.pl
        a b c d e f g h i j
        k l m n o p q r s t
        u v x y z
        

        【讨论】:

        • my @myArray = 'a' .. 'z' 不要输入任何多余的内容
        • print map({ not( ($_ + 1) % 10) ? "$x[$_]\n" : "$x[$_] " } 0 .. $#x), "\n";
        • 这是一个很好的答案,你应该发布它!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-16
        • 1970-01-01
        • 2023-01-30
        • 1970-01-01
        相关资源
        最近更新 更多