Ada sejumlah elemen dalam input Anda:
say elems <1 1 0 2 0 2 1 2 2 2 4 4 3 3>; # 14
grepBlok Anda mengkonsumsi dua elemen setiap kali:
{$^a eq $^b}
Jadi, jika Anda menambah atau menghapus elemen Anda akan mendapatkan kesalahan yang Anda dapatkan ketika blok dijalankan pada elemen tunggal yang tersisa di akhir.
Ada banyak cara untuk menyelesaikan masalah Anda.
Tetapi Anda juga bertanya tentang opsi untuk memungkinkan tumpang tindih jadi, misalnya, Anda mendapatkan dua (2 2)sub-daftar saat urutan 2 2 2ditemui. Dan, dalam nada yang sama, Anda mungkin ingin melihat dua pertandingan, bukan nol, dengan input seperti:
<1 2 2 3 3 4>
Jadi saya akan fokus pada solusi yang menangani masalah itu juga.
Meskipun ruang solusi menyempit untuk mengatasi masalah tambahan, masih ada banyak cara untuk mengekspresikan solusi secara fungsional.
Salah satu cara yang menambahkan kode sedikit lebih banyak ke akhir Anda:
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
The .rotorMetode mengubah daftar ke daftar sub-daftar, masing-masing sama panjang. Misalnya, say <1 2 3 4> .rotor: 2menampilkan ((1 2) (3 4)). Jika argumen panjang adalah pasangan, maka kuncinya adalah panjang dan nilainya adalah offset untuk memulai pasangan berikutnya. Jika offset negatif, Anda mendapatkan tumpang tindih sub-daftar. Dengan demikian say <1 2 3 4> .rotor: 2 => -1menampilkan ((1 2) (2 3) (3 4)).
The .flatMetode "merata" invocant nya. Misalnya, say ((1,2),(2,3),(3,4)) .flatmenampilkan (1 2 2 3 3 4).
Cara yang mungkin lebih mudah dibaca untuk menulis solusi di atas adalah dengan menghilangkan flatdan menggunakan .[0]dan .[1]mengindeks ke dalam sub-daftar yang dikembalikan oleh rotor:
say @s .rotor( 2 => -1 ) .grep: { .[0] eq .[1] }
Lihat juga komentar Elizabeth Mattijsen untuk variasi lain yang digeneralisasi untuk ukuran sub-daftar apa pun.
Jika Anda membutuhkan pola pengkodean yang lebih umum, Anda mungkin menulis sesuatu seperti:
say @s .pairs .map: { .value xx 2 if .key < @s - 1 and [eq] @s[.key,.key+1] }
The .pairsmetode pada daftar mengembalikan daftar pasangan, masing-masing pasangan sesuai dengan masing-masing unsur dalam daftar invocant nya. Masing .key-masing pasangan adalah indeks elemen dalam daftar yang tidak diundang; itu .valueadalah nilai elemen.
.value xx 2bisa saja ditulis .value, .value. (Lihat xx.)
@s - 1adalah jumlah elemen dalam @sminus 1.
The [eq]dalam [eq] listadalah pengurangan .
Jika Anda memerlukan pencocokan pola teks untuk memutuskan apa yang merupakan elemen yang berdekatan yang berdekatan, Anda dapat mengubah daftar input menjadi string, cocokkan dengan yang menggunakan salah satu kata keterangan pertandingan yang menghasilkan daftar kecocokan, lalu petakan dari daftar kecocokan yang dihasilkan ke yang Anda inginkan hasil. Untuk mencocokkan dengan tumpang tindih (mis. 2 2 2Hasil ((2 2) (2 2))digunakan :ov:
say @s .Str .match( / (.) ' ' $0 /, :ov ) .map: { .[0].Str xx 2 }
2 2 2 2itu mencetak 3(2 2)s seperti yang diharapkan. Belum pernah mendengar tentang metode inirotorSaya awalnya datang dengansquishmetode dan memeriksa apakah ia memiliki fitur atau argumen seperti@s.squish(:length 2, :multiple_instances yes)tetapi tidak memiliki fitur seperti itu dan itu tidak cocok untuk tugas itu. Dibandingkan dengansquish,rotorsepertinya cukup pas. Sebenarnya itu mungkin yang paling cocok untuk jenis operasi ini.