如何以各种可能的方式分割字符串?

Jim*_*ger 20 split raku

给定单词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)
  • 获取字符串枚举的所有组合(除了第0个)以确定分割位置
  • 然后将枚举修饰的字符串剪切到这些位置上,同时动态生成条件块
  • 最后取消修饰枚举并加入分割值

要得到

>>> $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撤消,最后的结果如下。