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