如何将子例程的参数展平为数组?

时间:2013-03-30 18:24:14

标签: perl

考虑以下脚本:

use strict;
use Data::Dumper;

my @arr=('1A','2A');
my $arr_ref=['1','2'];

sub routine1
{
my @arr=@_;
print Dumper(\@arr);
}

routine1(@arr,'one_A');

sub routine2
{
my $arr_ref=[@_];
print Dumper($arr_ref);
}

routine2($arr_ref,'one');

routine1正在使用@arr,而例程2正在使用$arr_ref

routine1打印以下内容:

$VAR1 = [
         '1A',
         '2A',
         'one_A'
        ];

routine2打印以下内容:

$VAR1 = [
         [
           '1',
           '2'
         ],
         'one'
        ];

我想继续在@_中使用arr_refroutine2,但想要提出以下输出:

$VAR1 = [
         '1',
         '2'
         'one'
        ];

有人可以建议出路吗?

3 个答案:

答案 0 :(得分:3)

使用函数ref,您可以看到标量是否为引用(如果是,则为哪种类型)。在一个简单的情况下,只传递数组引用,你可以简单地使用它来展平输入。

#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;

sub test {
  my @arr = map { ref() ? @$_ : $_ } @_;
  print Dumper \@arr;
}

test( ['a', 'b'], 1 );

作为一个附带好处,如果传递对另一个类型的引用,则此代码将会消息,因为您尝试将数组作为数组。如果需要处理更多,则需要检查引用类型。这开始迅速增加复杂性。

#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;

sub test {
  my @arr = map { 
    my $type = ref;
    if ( ! $type ) {
      $_;
    } elsif ( $type eq 'ARRAY' ) {
      @$_;
    } elsif ( $type eq 'HASH' ) {
      %$_;
    } else {
      ()
    }
  } @_;
  print Dumper \@arr;
}

test( ['a', 'b'], { p => 'q' }, 1 );

通过返回其他引用类型的空列表,我默默地忽略所有其他引用类型。或者您可能更愿意对其他引用类型强制进行字符串化。

...
} else {
  "$_";
}
...
test( ['a','b'], sub{}, bless({},'MyClass'), 1 ); 

使用这些处理中的哪一个取决于你的用例。

答案 1 :(得分:1)

前几天刚写完这篇文章。

sub flatten {
    return map { ref($_) ? flatten(@{$_}) : ($_) } @_;
}

答案 2 :(得分:0)

这个程序显示了一个子程序flatten,它将压缩简单数据和数组引用的混合列表,嵌套到任何级别。

use strict;
use warnings;

use Data::Dump;

my @arr = qw/ 1A 2A /;
my $arr_ref = [1, 2];

sub flatten;

routine1(@arr, 'one_A');
routine2($arr_ref, 'one');

sub routine1 {
  my @arr=@_;
  dd \@arr;
}

sub routine2 {
  my $arr_ref = [flatten @_];
  dd $arr_ref;
}

sub flatten {
  my $i = 0;
  while ($i < @_) {
    my $item = $_[$i];
    if (ref $item eq 'ARRAY') {
      splice @_, $i, 1, @$item;
    }
    else {
      ++$i;
    }
  }
  @_;
}

<强>输出

["1A", "2A", "one_A"]
[1, 2, "one"]