Split on Split overlap [RAKU] - PullRequest
       5

Split on Split overlap [RAKU]

6 голосов
/ 13 февраля 2020

Я наткнулся на «странное» поведение, когда попытался проанализировать многострочную строку (со строками, разделенными табуляцией) с намерением найти все значения, разделенные табуляцией, используя два разбиения в строке:

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

«Странное» поведение в 3-м и 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

, но мой вопрос касается внутренней работы "неправильного" кода. Как Раку пришел к такому результату?

Ответы [ 2 ]

9 голосов
/ 13 февраля 2020

Вы разделяете результат первого разделения, которое является списком; метод 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 , чтобы получить slip в более широкий массив.

3 голосов
/ 17 февраля 2020

Если вы хотите, чтобы ваше разделение давало вам отдельные фрагменты в виде одного списка, а не списка списков, вы можете использовать вариант метода разделения, который принимает список разделителей для разделения:

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 сам разделитель будет в списке результатов.

...