给定单词abcd
,我将如何构建以下嵌套列表?
[ (abcd) (a bcd) (ab cd) (abc d) (a b cd) (a bc d) (ab c d) (a b c d) ]
Run Code Online (Sandbox Code Playgroud)
即以各种可能的方式拆分单词,同时保持字母顺序。
#raku-beginner 上的 Nemokosch 向我指出了.combinations
该模块snip
,但我无法将它们组合在一起。
wam*_*mba 19
您可以match
使用:exhaustive
:
"abcd"
andthen .match: /^ (\w+)+ $/,:ex
andthen .map: *.[0].put
Run Code Online (Sandbox Code Playgroud)
Mus*_*dın 14
use v6.e.PREVIEW; # for `snip`
my $s = "abcd";
my @ps = $s.comb.pairs;
my $res = (1..^$s.chars
==> combinations()
==> map({ @ps.snip: (&{.key < $OUTER::_} for $_) })
==> map( *>>.value>>.join ));
Run Code Online (Sandbox Code Playgroud)
要得到
>>> $res
((abcd) (a bcd) (ab cd) (abc d) (a b cd) (a bc d) (ab c d) (a b c d))
Run Code Online (Sandbox Code Playgroud)
[其他答案++更简洁,但据我了解,它并不懒惰,并且在较大的字符串上执行速度稍慢,例如“abcd”x 5,所以我保留这个答案。]
这是中间结果:
# enumerated string
>>> @ps = $s.comb.pairs
[0 => a 1 => b 2 => c 3 => d]
# combinations of the enumeration except 0s
# these are the splitting points actually
>>> $combs = (1..^$s.chars).combinations
(() (1) (2) (3) (1 2) (1 3) (2 3) (1 2 3))
Run Code Online (Sandbox Code Playgroud)
从这些分割点中,我们可以生成例如(*.key < 1,)
和(*.key < 1, *.key < 3)
列表,以便我们可以将它们传递给列表,@ps.snip
然后列表将查看其元素的键,即索引位置,并为我们分割它们。所以这一代的下一步是:
# output is actually different but this is for demonstration
>>> $combs.map({ (&{.key < $OUTER::_} for $_) })
((), (*.key < 1), (*.key < 2), (*.key < 3), (*.key < 1, *.key < 2) ... (*.key < 1, *.key < 2, *.key < 3)
Run Code Online (Sandbox Code Playgroud)
(第一个空“条件”可以方便地生成稍后的字符串,因此我们不单独处理这种情况。)
对于每个组合,例如 (1, 2),我们迭代此 ( for $_
) 并生成条件。1 和 2 将依次出现$_
在后置形式的 for 循环中,但如果我们将其作为{.key < $_}
条件,则$_
不会在 1 和 2 上结束,而是在调用时传递的参数,即枚举对。但我们不希望这样,所以我们说将 OUTER 块的 放在这里$_
,它将依次为 1 和 2。但是对于.key
,我们确实希望在调用时得到该对,所以它$_.key
(没有 ,$_
因为它可以被省略。)
此时,剪断后我们有
>>> $combs.map({ @ps.snip: (&{.key < $OUTER::_} for $_) }).raku
(((0 => "a", 1 => "b", 2 => "c", 3 => "d"),).Seq, ((0 => "a",), (1 => "b", 2 => "c", 3 => "d")).Seq, ((0 => "a", 1 => "b"), (2 => "c", 3 => "d")).Seq, ((0 => "a", 1 => "b", 2 => "c"), (3 => "d",)).Seq, ((0 => "a",), (1 => "b",), (2 => "c", 3 => "d")).Seq...)
Run Code Online (Sandbox Code Playgroud)
我们有所需的分割,但有额外的负担:枚举和分割为字符。所以我们把.comb.pairs
开头的done和>>.value>>.join
结尾的done撤消,最后的结果如下。