【问题标题】:Split on Split overlap [ RAKU ]在拆分重叠时拆分 [RAKU]
【发布时间】:2020-02-13 09:21:57
【问题描述】:

当我尝试解析多行字符串(使用制表符分隔的字符串)以查找所有由制表符分隔的值时,我偶然发现了一种“奇怪”的行为:

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

“奇怪”行为出现在结果序列的第 3d 和第 5 个成员中。似乎某行“预期”的最后一个字符串和后续行的第一个字符串有重叠。

我的期望是这样的:

("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

但我的问题是关于“错误”代码的内部工作原理。 Raku 是如何得出这个结果的?

【问题讨论】:

  • 如果您在文字上进行拆分,作为仅供参考,使用字符串进行拆分会在内部更快(或者至少以前是这样)(它不必采用正则表达式) :$s.split("\n")».split("\t") 或者,正如 lizmat 在 cmets 中提到的,$s.lines>>.split("\t")

标签: split raku


【解决方案1】:

您正在拆分第一次拆分的结果,这是一个列表; split 方法会将调用的任何内容强制转换为字符串,然后将其拆分。列表将字符串化(通过其Str 方法)到其成员,由单个空格分隔。这就是为什么某些结果字段有两个 L 和 C 对以及它们之间的空格的原因。

这会得到你想要的结果:

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 以使其滑入到更宽的数组中。

【讨论】:

  • 另外:$s.split(/\n/) 写成$s.lines 可能更好
【解决方案2】:

如果您希望拆分将各个部分作为一个列表而不是列表列表提供给您,则可以使用 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 分隔符本身将在结果列表中。

【讨论】:

    猜你喜欢
    • 2020-10-18
    • 1970-01-01
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-09
    • 2018-08-01
    • 1970-01-01
    相关资源
    最近更新 更多