如何在Perl 6中"扁平化"一个列表?

12

假设我想要从a、b和c中选出2个字母的所有排列组合。

我可以这样做:

my @perm = <a b c>.combinations(2)».permutations;
say @perm;
# [((a b) (b a)) ((a c) (c a)) ((b c) (c b))]

这很接近我需要的,但不完全是。如何“展开”它,以便我得到:

# [(a b) (b a) (a c) (c a) (b c) (c b)]

?


这看起来像是一个重复的问题,https://dev59.com/am435IYBdhLWcg3w3EIi - FuePi
7
@FuePi,完全不是这样。Perl 5 ≠ Perl 6. - mscha
4个回答

14

还可以参考一种更好的方式来实现我(OP)想要的

还可以参考“如何完全展平Raku列表(列表(列表)……)”问题的“一些可能的解决方案”答案

添加一个下标

my \perm = <a b c>.combinations(2)».permutations;
say perm;       # (((a b) (b a)) ((a c) (c a)) ((b c) (c b)))
say perm[*];    # (((a b) (b a)) ((a c) (c a)) ((b c) (c b)))
say perm[*;*];  # ((a b) (b a) (a c) (c a) (b c) (c b))
say perm[*;*;*] # (a b b a a c c a b c c b)

注释

我使用了非Sigil变量,因为我认为对于不熟悉Raku的人来说,这样更清晰。

我没有将下标附加到原始表达式上,但我本可以这样做:

my \perm = <a b c>.combinations(2)».permutations[*;*];
say perm;       # ((a b) (b a) (a c) (c a) (b c) (c b))

我喜欢[*;*]技巧来“展平”列表,但我不喜欢无Sigil变量,这对于那些了解Perl(5或6)的人来说非常清晰。 - mscha
@Larry对多维数组的推测/规范(http://design.perl6.org/S09.html#Multidimensional_arrays)非常有趣。其中一些简单的部分,比如这个“技巧”,已经在v6.c和Rakudo Perl 6编译器中实现了。 - raiph

10

最终,您一开始就以错误的方式构建了列表。您可以像这样将排列插入外部列表中。slip

<a b c>.combinations(2).map(|*.permutations);

以下是生成的列表

((a b) (b a) (a c) (c a) (b c) (c b)) 

根据 Bench 模块,这比原来的方法快了大约 300%。

<a b c>.combinations(2).map(*.permutations)[*;*]

1
谢谢,这确实是更好的完成我想要的方式。不过,我没有将其标记为最佳答案,因为它并不严格回答我所问的问题。 :) - mscha

9
通过适当插入slips,例如通过。
<a b c>.combinations(2).map(*.permutations.Slip).Array

或者
[ slip .permutations for <a b c>.combinations(2) ]

在第一个示例中,如果您满意使用Seq,则调用.Array是不必要的,并且可以用.list.cache(由PositionalBindFailover提供)替换,如果不需要可变性。
在第二个示例中,可以使用前缀|运算符代替slip子。

“».”和“map”不是等价的。前者是自动线程的候选项。创建一个少一级的LoL可能不是他想要的。 - user5854207
@gfldex:如果你想要的话,你总是可以加入一个.hyper调用;另外请注意,在你的例子中,组合列表被迭代了两次。 - Christoph
谢谢,.Slip就是我需要的技巧。很遗憾.Slip似乎不起作用... - mscha
@mscha:超级运算符可以进入嵌套结构,因此您正在滑动单元素叶子,这是无操作。 - Christoph
@Christoph,我认为那不是真的,否则 ».permutations 部分也不会起作用。 - mscha
@mscha:这是因为permutations方法被注释为 nodal特征(参见Any.pmList.pm),防止超级运算符执行深度映射(参见metaops.pm,查找METAOP_HYPER_POSTFIX);不确定用户文档是否解释了这一点,但在设计文档中提到了。 - Christoph

5
my @perm = <a b c>.combinations(2)».permutations;
dd [ @perm.map(*.Slip) ]
# OUTPUT«[("a", "b"), ("b", "a"), ("a", "c"), ("c", "a"), ("b", "c"), ("c", "b")]␤»

然而,在程序后面使用时,您最好拆解 LoL。在长列表上进行映射可能需要很长时间。


谢谢,.Slip 是我需要的技巧。很遗憾 ».Slip 似乎不起作用... - mscha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接