多维数组中移除一些元素后不能使用普通数组。

3

如何在多维数组中删除“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数组。换句话说,如何将其线性化?

3
你说的话很难理解。 "D. one. IOW" 意味着什么? - TLP
2
注意:此问题已经发布到 https://www.perlmonks.org/?node_id=11139965 - Dave Sherohman
你能展示一下你想要得到的最终数组吗? - brian d foy
1个回答

5

需要取消引用数组引用的元素并复制数据。对于单层:

@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;
}

在这里,人们也可以使用poppush,以不同的组合方式。以上保持顺序,尽可能地将复杂结构缩减为一个扁平化的结构。

如果还有其他的复杂性,比如其他类型的引用(它们本身包含要解包的数组引用),那么就需要相应地进行调整。此外,还需要添加检查功能,特别是针对循环引用。请参见此SO页面此perlmonks页面


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接