У вашому введенні є парна кількість елементів:
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Кожної пари є індексом елемента в списку invocant; the .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здається, цілком підходить. Насправді це може бути навіть найкращим для цього типу операцій.