如何在多维数组中删除“1”后得到纯数组?
@p=();
my @l=([9,7],[3,4]);
push(@p,['FOO',[@l]]);
push(@p,['BAR',[[8,0]]]);
splice(@$_,0,1) for @p;
print "\n",@$_ for @p;
ARRAY(0x5624cf01e340)
ARRAY(0x5624cf028d78)
我们如何将内部/第二维中大小为1x2的数字数量简化成一个简单/普通的2D数组。换句话说,如何将其线性化?
如何在多维数组中删除“1”后得到纯数组?
@p=();
my @l=([9,7],[3,4]);
push(@p,['FOO',[@l]]);
push(@p,['BAR',[[8,0]]]);
splice(@$_,0,1) for @p;
print "\n",@$_ for @p;
ARRAY(0x5624cf01e340)
ARRAY(0x5624cf028d78)
需要取消引用数组引用的元素并复制数据。对于单层:
@ary = map { ref eq "ARRAY" ? @$_ : $_ } @ary;
ref内置函数默认采用$_
作为参数。另外建议考虑使用Scalar::Util中的reftype
代替,或者使用Ref::Util中的is_arrayref
。简单明了的情况下,内置函数是可行的。
如果有更深层次的嵌套,请在每个层级上使用上述方法。对于这个问题的要求,保留两级深度输入数据中的一级嵌套即可。
for my $elem (@p) {
@$elem = map { ref eq "ARRAY" ? @$_ : $_ } @$elem;
}
由于$elem
为@p
的当前元素的别名,所以此代码在原地更改数组。
如果还存在进一步的层次,可能深度不同,可以使用递归或迭代进行处理。 简单的实现方式如下:
递归:
sub flatten_recurse {
return map { ref eq 'ARRAY' ? flatten_recurse(@$_) : $_ } @_
}
sub flatten_iter {
my @deque = @_;
my @flat;
while (@deque) {
my $front = shift @deque;
if (ref($front) eq 'ARRAY') {
unshift @deque, @$front;
} else {
push @flat, $front;
}
}
return \@flat;
}
在这里,人们也可以使用pop
和push
,以不同的组合方式。以上保持顺序,尽可能地将复杂结构缩减为一个扁平化的结构。
如果还有其他的复杂性,比如其他类型的引用(它们本身包含要解包的数组引用),那么就需要相应地进行调整。此外,还需要添加检查功能,特别是针对循环引用。请参见此SO页面和此perlmonks页面。