我如何才能完全展平一个列表(的列表(的列表)...) [英] How can I completely flatten a list (of lists (of lists) ... )

查看:54
本文介绍了我如何才能完全展平一个列表(的列表(的列表)...)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何才能完全弄平列表以及包含列表的内容.除其他事项外,我想出了一种解决方案,可以将具有多个元素的东西放回去并放回去,或者将具有一个元素的东西放回去.

I was wondering about how I could completely flatten lists and things that contain them. Among other things, I came up with this solution that slips things that have more than one element and puts them back, or takes things with one element after slipping it.

这与在perl 6中如何拉平"列表列表有些不同?并非完全平坦,因为任务是进行重组.

This is a bit different than How do I "flatten" a list of lists in perl 6?, which doesn't completely flat because the task is to restructure.

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

But, maybe there's a better way.

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答案:

Curiously, I also read some python answers:

itertools.chain(* sublist)看起来很有趣,但是答案要么是递归的,要么是硬编码的两个级别.功能语言在源代码中是递归的,但我希望如此.

itertools.chain(*sublist) look interesting, but the answers were either recursive or limited to two levels from hard-coding. The functional languages were recursive in the source code, but I expected that.

推荐答案

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

Unfortunately there's no direct built-in that completely flattens a data structure even when sub-lists are wrapped in item containers.

一些可能的解决方案:

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

You've already come up with a solution like this, but deepmap can take care of all the tree iteration logic to simplify it. Its callback is called once for every leaf node of the data structure, so using take as the callback means that gather will collect a flat list of the leaf values:

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

自定义递归函数

您可以使用像这样的子例程将列表递归地 slip 进入其父级:

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

另一种方法是将<> 递归应用于子列表,以使它们摆脱包装在其中的任何项目容器,然后在其上调用 flat 结果:

Another approach would be to recursively apply <> to sub-lists to free them of any item containers they're wrapped in, and then call flat on the result:

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

多维数组索引

postcircumfix [] 运算符可以与多维下标一起使用,以获取直至一定深度的叶节点的平面列表,尽管遗憾的是尚未实现无限深度"版本:

Multi-dimensional array indexing

The postcircumfix [ ] operator can be used with a multi-dimensional subscript to get a flat list of leaf nodes up to a certain depth, though unfortunately the "infinite depth" version is not yet implemented:

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.

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

Still, if you know the maximum depth of your data structure this is a viable solution.

内置的 flat 函数可以将深度嵌套的列表列表变平.问题在于它不属于项目容器( Scalar s).嵌套列表中意外容器的常见来源是:

The built-in flat function can flatten a deeply nested lists of lists just fine. The problem is just that it doesn't descend into item containers (Scalars). Common sources of unintentional item containers in nested lists are:

  • Array (但不是 List )将其每个元素包装在新鲜的项目容器中,无论之前是否有过.

  • An Array (but not List) wraps each of its elements in a fresh item container, no matter if it had one before.

  • 如何避免:如果不需要Array提供的可变性,请使用列表列表而不是数组数组.可以使用与:= 的绑定(而不是赋值)进行绑定,以将 List 存储在 @ 变量中,而无需将其转换为 Array :
  • How to avoid: Use Lists of Lists instead of Arrays of Arrays, if you don't need the mutability that Array provides. Binding with := can be used instead of assignment, to store a List in a @ variable without turning it into an Array:

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

$ 变量是项目容器.

  • 如何避免:将列表存储在 $ 变量中,然后将其作为元素插入到另一个列表中时,请使用<> 对其进行去容器化.将父列表的容器传递给 flat 时,也可​​以使用 | 绕过它:
  • How to avoid: When storing a list in a $ variable and then inserting it as an element into another list, use <> to decontainerize it. The parent list's container can also be bypassed using | when passing it to flat:

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

这篇关于我如何才能完全展平一个列表(的列表(的列表)...)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆