В вашем входе четное количество элементов:
say elems <1 1 0 2 0 2 1 2 2 2 4 4 3 3>; # 14
Ваш grepблок потребляет два элемента каждый раз:
{$^a eq $^b}
Поэтому, если вы добавите или удалите элемент, вы получите ошибку, которую вы получите, когда блок будет запущен для одного элемента, оставшегося в конце.
Есть много способов решить вашу проблему.
Но вы также спросили о возможности разрешения наложения, так что, например, вы получаете два (2 2)подсписка, когда 2 2 2встречается последовательность . И в аналогичном ключе вы, вероятно, хотите видеть два совпадения, а не ноль, с такими входными данными:
<1 2 2 3 3 4>
Поэтому я сосредоточусь на решениях, которые также касаются этих проблем.
Несмотря на сужение пространства решений для решения дополнительных проблем, есть еще много способов выразить решения функционально.
Один способ, который просто добавляет немного кода в конец вашего:
my @s = <1 1 0 2 0 2 1 2 2 2 4 4 3 3>;
say grep {$^a eq $^b}, @s .rotor( 2 => -1 ) .flat
.rotorМетод преобразует список в список подсписков, каждый из одной и той же длины. Например, say <1 2 3 4> .rotor: 2отображает ((1 2) (3 4)). Если аргумент длины является парой, то ключ является длиной, а значение является смещением для начала следующей пары. Если смещение отрицательное, вы получаете перекрытие подсписка. Таким образом say <1 2 3 4> .rotor: 2 => -1отображает ((1 2) (2 3) (3 4)).
В .flatметоде «» его более плоский invocant. Например, say ((1,2),(2,3),(3,4)) .flatотображает (1 2 2 3 3 4).
Возможно, более читаемый способ написания вышеприведенного решения состоит в том, чтобы опустить flatи использовать .[0]и .[1]индексировать в подсписки, возвращаемые rotor:
say @s .rotor( 2 => -1 ) .grep: { .[0] eq .[1] }
Смотрите также комментарий Элизабет Маттийсен для другого варианта, который обобщает для любого размера подсписка.
Если вам нужен более общий шаблон кодирования, вы можете написать что-то вроде:
say @s .pairs .map: { .value xx 2 if .key < @s - 1 and [eq] @s[.key,.key+1] }
.pairsМетод в списке возвращает список пара, каждую пару , соответствующую каждый из элементов в его invocant списка. Значение .keyкаждой пары - это индекс элемента в списке инвокантов; .valueявляется значением элемента.
.value xx 2мог быть написан .value, .value. (См xx.)
@s - 1количество элементов в @sминус 1.
[eq]В [eq] listэто сокращение .
Если вам нужно сопоставление с текстовым шаблоном, чтобы решить, из чего состоят смежные равные элементы, вы можете преобразовать входной список в строку, сопоставьте ее с помощью одного из наречий совпадений, которые генерируют список совпадений, а затем сопоставьте полученный итоговый список совпадений с вашим желаемым результат. Чтобы соответствовать с перекрытиями (например, 2 2 2результаты в ((2 2) (2 2))использовании :ov:
say @s .Str .match( / (.) ' ' $0 /, :ov ) .map: { .[0].Str xx 2 }
2 2 2 2она печатает 3(2 2)с, как и ожидалось. Никогда не слышал о методе,rotorя изначально придумал этотsquishметод и проверил, есть ли у него такие особенности или аргументы, как у него,@s.squish(:length 2, :multiple_instances yes)но у него не было таких функций, и он не подходит для этой задачи. По сравнению сsquish,rotorкажется, вполне подходит. На самом деле это может быть даже самый подходящий для этого типа операции.