如何彻底平整Perl 6列表(列表(列表)…)

前端之家收集整理的这篇文章主要介绍了如何彻底平整Perl 6列表(列表(列表)…)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想知道我如何能够完全压扁包含它们的列表和内容.除此之外,我想出了这样一个解决方案,它将有不止一个元素的东西放回去,或者在滑倒之后用一个元素来处理东西.

这与How do I “flatten” a list of lists in perl 6?有点不同,因为任务是重组,这并不完全平坦.

但是,也许有更好的方法.

my @a  = 'a',('b','c' );
my @b  = ('d',),'e','f',@a;
my @c  = 'x',$( 'y','z' ),'w';

my @ab = @a,@b,@c;
say "ab: ",@ab;

my @f = @ab;

@f = gather {
    while @f {
        @f[0].elems == 1 ??
            take @f.shift.Slip
                !!
            @f.unshift( @f.shift.Slip )
        }
    }

say "f: ",@f;

这给出:

ab: [[a (b c)] [(d) e f [a (b c)]] [x (y z) w]]
f: [a b c d e f a b c x y z w]

奇怪的是,我也读了一些python的答案:

> Making a flat list out of list of lists in Python
> How flatten a list of lists one step
> flatten list of lists of lists to a list of lists

itertools.chain(*子列表)看起来很有趣,但答案是递归的,或者限于硬编码的两个级别.功能语言在源代码中递归,但我预计.

解决方法

不幸的是,即使子列表被包装在项目容器中,也没有直接的内置功能可以完全平坦化数据结构.

一些可能的解决方案:

收集/取

您已经提出了这样的解决方案,但是deepmap可以处理所有的树式迭代逻辑来简化它.对于数据结构的每个叶节点,它的回调被调用一次,因此使用take作为回调方法,即收集将收集叶值的平面列表:

sub reallyflat (+@list) { gather @list.deepmap: *.take }

自定义递归函数

您可以使用这样的子程序将列表递归递送到父级中:

multi reallyflat (@list) { @list.map: { slip reallyflat $_ } }
multi reallyflat (\leaf) { leaf }

另一种方法是递归地应用<到子列表中释放他们包装的任何物品容器,然后调用结果:

sub reallyflat (+@list) {
    flat do for @list {
        when Iterable { reallyflat $_<> }
        default       { $_               }
    }
}

多维数组索引

postcircumfix []运算符可以与多维下标一起使用,以获得一定长度的叶节点的平面列表,尽管不幸的是“无限深度”版本尚未实现:

say @ab[*;*];     # (a (b c) (d) e f [a (b c)] x (y z) w)
say @ab[*;*;*];   # (a b c d e f a (b c) x y z w)
say @ab[*;*;*;*]; # (a b c d e f a b c x y z w)
say @ab[**];      # HyperWhatever in array index not yet implemented. Sorry.

但是,如果您知道数据结构的最大深度,这是一个可行的解决方案.

避免集装箱化

内置的平面功能可以平滑一个深入嵌套的列表列表.问题在于它不会下降到项目容器(Scalars)中.嵌套列表中无意的项目容器的常见来源有:

>一个数组(但不是列表)将其每个元素包装在一个新的项目容器中,无论以前是否有一个元素.

>如何避免:使用列表而不是数组数组,如果您不需要Array提供的可变性.绑定:=可以使用而不是赋值,将列表存储在@变量中,而不将其转换为数组:

my @a  := 'a','c' );
my @b  := ('d',@a;
say flat @b; # (d e f a b c)

> $变量是项容器.

>如何避免:将列表存储在$变量中,然后将其作为元素插入到另一个列表中时,使用<>去掉它.也可以使用|绕过父列表的容器当把它传递给平:

my $a = (3,4,5);
my $b = (1,2,$a<>,6);
say flat |$b;  # (1 2 3 4 5 6)

猜你在找的Perl相关文章