考虑以下脚本:
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_ref
和routine2
,但想要提出以下输出:
$VAR1 = [
'1',
'2'
'one'
];
有人可以建议出路吗?
答案 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"]