bri*_*foy 17 list flatten perl6 raku
我想知道如何完全展平列表和包含它们的东西.除此之外,我想出了这个解决方案,它可以滑动具有多个元素的东西并将它们放回去,或者在滑动之后用一个元素取出它.
这与我如何"压扁"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;
Run Code Online (Sandbox Code Playgroud)
这给出了:
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]
Run Code Online (Sandbox Code Playgroud)
奇怪的是,我还阅读了一些python答案:
itertools.chain(*sublist)看起来很有趣,但答案要么是递归的,要么限于硬编码的两个级别.功能语言在源代码中是递归的,但我希望如此.
遗憾的是,即使子列表包含在项容器中,也没有直接内置来完全展平数据结构.
一些可能的解决方
您已经提出了这样的解决方案,但deepmap可以处理所有树迭代逻辑以简化它.它的回调被调用一次用于数据结构的每个叶节点,因此使用take回调意味着gather将收集叶值的平面列表:
sub reallyflat (+@list) { gather @list.deepmap: *.take }
Run Code Online (Sandbox Code Playgroud)
您可以使用这样的子例程递归slip列入其父级:
multi reallyflat (@list) { @list.map: { slip reallyflat $_ } }
multi reallyflat (\leaf) { leaf }
Run Code Online (Sandbox Code Playgroud)
另一种方法是递归地应用于<>子列表以释放它们包含的任何项容器,然后调用flat结果:
sub reallyflat (+@list) {
flat do for @list {
when Iterable { reallyflat $_<> }
default { $_ }
}
}
Run Code Online (Sandbox Code Playgroud)
该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.
Run Code Online (Sandbox Code Playgroud)
但是,如果您知道数据结构的最大深度,这是一个可行的解决方案.
内置flat函数可以很好地压缩深度嵌套的列表列表.问题只是它没有下降到项容器中Scalar.嵌套列表中无意项容器的常见来源是:
一个Array(但不是List)将每个元素包装在一个新的项目容器中,无论它之前是否有一个.
:=可以使用绑定而不是赋值,将变量存储List在@变量中而不将其转换为Array:
my @a := 'a', ('b', 'c' );
my @b := ('d',), 'e', 'f', @a;
say flat @b; # (d e f a b c)$ 变量是项容器.
$变量中,然后将其作为元素插入到另一个列表中时,用于对其<>进行去包容.父代表的容器也可以|在将其传递给时使用flat:my $a = (3, 4, 5); my $b = (1, 2, $a<>, 6);
say flat |$b; # (1 2 3 4 5 6)
我不知道有这样做的内置方法,尽管可能很好(如果没有,可能应该有).
我能在短时间内提出的最好的是:
gather @ab.deepmap(*.take)
Run Code Online (Sandbox Code Playgroud)
我不确定如何收集/采用可能并行化的超级运算符评估,因此以下替代方案可能不安全,特别是如果您关心元素顺序:
gather @ab>>.take
Run Code Online (Sandbox Code Playgroud)
如果您需要一个数组或通过它将其重新列入一个列表,您可以将代码放入方括号中.list.
最后,这是第一个作为复古风格子程序重新设置的解决方案:
sub deepflat { gather deepmap &take, @_ }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
560 次 |
| 最近记录: |