gpt4 book ai didi

list - 我怎样才能完全展平一个列表(列表(列表)......)

转载 作者:行者123 更新时间:2023-12-03 14:13:54 29 4
gpt4 key购买 nike

我想知道如何完全展平列表和包含它们的东西。除其他外,我想出了一个解决方案,它可以将具有多个元素的东西滑倒并将它们放回原处,或者在滑倒后将带有一个元素的东西拿走。

这与 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(*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 )将其每个元素包装在一个新的项目容器中,无论它之前是否有一个。
  • 如何避免:如果您不需要 Array 提供的可变性,请使用 Lists of Lists 而不是 Arrays of Arrays。与 := 绑定(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/41648119/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com