在子例程中解析多个数组

时间:2013-06-12 07:10:23

标签: perl

我有以下代码

    use strict;
    sub test {
       my($greeting, @names) = @_;
       my $returnString;

       foreach my $name (@names) {
           $returnString .= "$greeting, $name!\n";
       }

       return $returnString;
    }
    print &test("Hi", "Tim", "Tom", "Chris");

输出

    Hi Tim! Hi Tom! Hi Chris!

我希望能够添加多个数组。我尝试修改我的代码,如下所示

       my(@greeting, @names) = @_;
       print &test("Hi", "Tim", "Hello", "Tom", "Bye", "Chris");

但是我发现这是不可能做到的。从我所做的阅读中我认为我需要将参数作为参考传递。

        my($greeting, $names) = @_;
        my @names = $names; 

但我发现这只是输出         嗨,蒂姆!

处理这种情况的最佳方法是什么?

4 个答案:

答案 0 :(得分:4)

您确实需要将它们作为sub的引用传递给它们作为两个单独的数组而不是单个列表接收它们,您只是语法错误。试试这个:

my @greetings = qw( Hi Hello );
my @names = qw( Tim Tom Chris );

# Put a \ before the variable to get a reference to it
say_greetings(\@greetings, \@names);

sub say_greetings {
  my ($greeting_ref, $name_ref) = @_;

  # Put @ before an arrayref to get the array back
  my @greet = @$greeting_ref;
...
}

此外,您不应该习惯使用sub&次来电添加前缀。这是Perl 4的延续。在Perl 5中,它不是必需的,可能会产生意想不到的副作用。

答案 1 :(得分:3)

处理这种情况的最佳方法取决于您的需求。以下是几个选项:

  1. List::MoreUtils 'natatime'(如果订单很重要)

    use List::MoreUtils 'natatime';
    
    test( 'Hi', 'Tim', 'Hi', 'Tom' );
    
    sub test {
    
        warn( "Need to provide greeting-name pairs" ), # Check for
          return if @_ % 2;                            # data completeness
    
        my $iter = natatime, 2, @_;
    
        my $string;
        while ( my ( $greet, $name ) = $iter->() ) {
    
            $string .= "$greet $name!\n";
        }
    
        return $string;
    }
    
  2. 将传递的列表视为哈希(如果顺序无关紧要):

    test( 'Hi', 'Tim', 'Hi', 'Tom' );
    
    sub test {
    
        my %set = @_;  # warnings pragma checks for
                       # data completeness during runtime
    
        return join "\n", map { "$_ $set{$_}!" } keys %set;
    }
    
  3. 将键值对传递为arrayrefs(保留顺序,保证数据完整性):

    test( [ 'Hi', 'Tim' ], [ 'Hi', 'Tom' ] );
    
    sub test { join "\n", map { "@{$_}!" } @_ }
    

答案 2 :(得分:1)

您不必使用引用,按原样传递列表并迭代每一个元素,因为问候语和名称成对设置。

use strict;
use warnings;

sub test {
   my @arg = @_;

   my $returnString = "";
   foreach my $i (grep { ! ($_%2) } 0 .. $#arg) {

       my ($greeting, $name) = @arg[$i, $i+1];
       $returnString .= "$greeting, $name!\n";
   }

   return $returnString;
}

print test("Hi", "Tim", "Hello", "Tom", "Bye", "Chris");    

答案 3 :(得分:1)

希望这会有所帮助。如果问候语和姓名始终按顺序排列,则以下代码可以正常工作。

use strict;

test("Hi", "Tim", "Hello", "Tom", "Bye", "Chris");

sub test
{
        my $i;
        my $len = @_;

        for ($i = 0; $i < @_; $i += 2) {
                print "$_[$i] $_[$i + 1]\n"
        }
}

未完成输入验证。检查数组长度是2的倍数是不错的。