我想知道如何完全展平列表和包含它们的东西。除其他外,我想出了一个解决方案,它可以将具有多个元素的东西滑倒并将它们放回原处,或者在滑倒后将具有一个元素的东西拿走。
这与 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 答案:
itertools.chain(*sublist)
看起来很有趣,但答案要么是递归的,要么是硬编码的两个级别。函数式语言在源代码中是递归的,但我预料到了。
最佳答案
不幸的是,即使子列表包装在项目容器中,也没有直接的内置功能可以完全扁平化数据结构。
一些可能的解决方案:
收集/拍摄
您已经想出了这样的解决方案,但是 deepmap
可以处理所有的树迭代逻辑以简化它。它的回调对数据结构的每个叶节点调用一次,因此使用 take
因为回调意味着 gather
将收集叶子值的平面列表:
sub reallyflat (+@list) { gather @list.deepmap: *.take }
自定义递归函数
您可以使用这样的子程序递归地
slip
列出他们的 parent :multi reallyflat (@list) { @list.map: { slip reallyflat $_ } }
multi reallyflat (\leaf) { leaf }
另一种方法是递归应用
<>
到子列表以释放它们所包裹的任何项目容器,然后调用 flat
结果: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.
不过,如果您知道数据结构的最大深度,这是一个可行的解决方案。
避免容器化
内置
flat
函数可以很好地展平深度嵌套的列表列表。问题只是它没有下降到项目容器(Scalar
s)中。嵌套列表中意外项容器的常见来源是:Array
(但不是 List
)将其每个元素包装在一个新的项目容器中,无论它之前是否有一个。:=
绑定(bind)可以用来代替赋值来存储 List
在 @
变量而不将其转换为 Array
:my @a := 'a', ('b', 'c' );我的@b := ('d',), 'e', 'f', @a;
说平@b; # (d e f a b c)
$
变量是项目容器。$
中时变量,然后将其作为元素插入到另一个列表中,使用 <>
去容器化它。也可以使用 |
绕过父列表的容器。将其传递给 flat
时: 我的 $a = (3, 4, 5);我的 $b = (1, 2, $a<>, 6);
说平 |$b; # (1 2 3 4 5 6)
关于list - 我怎样才能完全展平一个列表(列表(列表)......),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67515479/