Split on Split 重叠 [ RAKU ]
Split on Split overlap [ RAKU ]
当我试图解析一个多行字符串(使用制表符分隔的字符串)以查找所有由制表符分隔的值时,我偶然发现了一个 "strange" 行为,使用连续两个拆分:
use v6.d; # 2020.01 release
my $s = "L1:C1\tL1:C2\tL1:C3\nL2:C1\tL2:C2\tL2:C3\nL3:C1\tL3:C2\tL3:C3";
say $s.split(/\n/).split(/\t/).raku;
对应的打印输出如下:
("L1:C1", "L1:C2", "L1:C3 L2:C1", "L2:C2", "L2:C3 L3:C1", "L3:C2", "L3:C3").Seq
"strange" 行为在结果序列的第 3d 和第 5 个成员中。好像一行的最后一个字符串"expected"和下一行的第一个字符串有重叠。
我的期望是:
("L1:C1", "L1:C2", "L1:C3", "L2:C1", "L2:C2", "L2:C3", "L3:C1", "L3:C2", "L3:C3").Seq
谁能详细解释一下这种行为的内部机制?
澄清一下,我知道正确的代码是:
$s.split(/\n/)>>.split(/\t/).flat.raku
但我的问题是关于 "wrong" 代码的内部工作原理。 Raku 是如何得出这个结果的?
你拆分的是第一次拆分的结果,是一个列表; split 方法会将调用它的任何内容强制转换为字符串,然后将其拆分。列表将(通过其 Str
方法)字符串化为其由单个 space 分隔的成员。这就是为什么一些结果字段有两个 L 和 C 对以及中间有一个 space 的原因。
这会得到你想要的结果:
say "L1:C1\tL1:C2\tL1:C3\nL2:C1\tL2:C2\tL2:C3\nL3:C1\tL3:C2\tL3:C3"
.split("\n")
.map( *.split( "\t" ).Slip )
因为它拆分了第一个拆分的结果,然后把它转换成一个Slip得到它滑动到更宽的数组中。
如果您希望拆分将各个部分作为一个列表而不是列表列表提供给您,您可以使用 split 方法的变体,它采用分隔符列表作为拆分依据:
say "L1:C1,L1:C2;L1:C3\nL2:C1-L2:C2|L2:C3^L3:C1".split([",", ";", "\n", "|", "^"]).raku;
# output: ("L1:C1", "L1:C2", "L1:C3", "L2:C1-L2:C2", "L2:C3", "L3:C1").Seq
将 :k
或 :v
副词传递给 split 方法调用会将分隔符作为单独的条目保留在结果列表中;使用 :k
时,该值将是分隔符列表中包含匹配分隔符的索引,使用 :v
时,分隔符本身将出现在结果列表中。
当我试图解析一个多行字符串(使用制表符分隔的字符串)以查找所有由制表符分隔的值时,我偶然发现了一个 "strange" 行为,使用连续两个拆分:
use v6.d; # 2020.01 release
my $s = "L1:C1\tL1:C2\tL1:C3\nL2:C1\tL2:C2\tL2:C3\nL3:C1\tL3:C2\tL3:C3";
say $s.split(/\n/).split(/\t/).raku;
对应的打印输出如下:
("L1:C1", "L1:C2", "L1:C3 L2:C1", "L2:C2", "L2:C3 L3:C1", "L3:C2", "L3:C3").Seq
"strange" 行为在结果序列的第 3d 和第 5 个成员中。好像一行的最后一个字符串"expected"和下一行的第一个字符串有重叠。
我的期望是:
("L1:C1", "L1:C2", "L1:C3", "L2:C1", "L2:C2", "L2:C3", "L3:C1", "L3:C2", "L3:C3").Seq
谁能详细解释一下这种行为的内部机制?
澄清一下,我知道正确的代码是:
$s.split(/\n/)>>.split(/\t/).flat.raku
但我的问题是关于 "wrong" 代码的内部工作原理。 Raku 是如何得出这个结果的?
你拆分的是第一次拆分的结果,是一个列表; split 方法会将调用它的任何内容强制转换为字符串,然后将其拆分。列表将(通过其 Str
方法)字符串化为其由单个 space 分隔的成员。这就是为什么一些结果字段有两个 L 和 C 对以及中间有一个 space 的原因。
这会得到你想要的结果:
say "L1:C1\tL1:C2\tL1:C3\nL2:C1\tL2:C2\tL2:C3\nL3:C1\tL3:C2\tL3:C3"
.split("\n")
.map( *.split( "\t" ).Slip )
因为它拆分了第一个拆分的结果,然后把它转换成一个Slip得到它滑动到更宽的数组中。
如果您希望拆分将各个部分作为一个列表而不是列表列表提供给您,您可以使用 split 方法的变体,它采用分隔符列表作为拆分依据:
say "L1:C1,L1:C2;L1:C3\nL2:C1-L2:C2|L2:C3^L3:C1".split([",", ";", "\n", "|", "^"]).raku;
# output: ("L1:C1", "L1:C2", "L1:C3", "L2:C1-L2:C2", "L2:C3", "L3:C1").Seq
将 :k
或 :v
副词传递给 split 方法调用会将分隔符作为单独的条目保留在结果列表中;使用 :k
时,该值将是分隔符列表中包含匹配分隔符的索引,使用 :v
时,分隔符本身将出现在结果列表中。