Ada sejumlah elemen dalam input Anda:
say elems <1 1 0 2 0 2 1 2 2 2 4 4 3 3>; # 14
grep
Blok 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 2
ditemui. 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 .rotor
Metode mengubah daftar ke daftar sub-daftar, masing-masing sama panjang. Misalnya, say <1 2 3 4> .rotor: 2
menampilkan ((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 => -1
menampilkan ((1 2) (2 3) (3 4))
.
The .flat
Metode "merata" invocant nya. Misalnya, say ((1,2),(2,3),(3,4)) .flat
menampilkan (1 2 2 3 3 4)
.
Cara yang mungkin lebih mudah dibaca untuk menulis solusi di atas adalah dengan menghilangkan flat
dan 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 .pairs
metode 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 .value
adalah nilai elemen.
.value xx 2
bisa saja ditulis .value, .value
. (Lihat xx
.)
@s - 1
adalah jumlah elemen dalam @s
minus 1.
The [eq]
dalam [eq] list
adalah 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 2
Hasil ((2 2) (2 2))
digunakan :ov
:
say @s .Str .match( / (.) ' ' $0 /, :ov ) .map: { .[0].Str xx 2 }
2 2 2 2
itu mencetak 3(2 2)
s seperti yang diharapkan. Belum pernah mendengar tentang metode inirotor
Saya awalnya datang dengansquish
metode 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
,rotor
sepertinya cukup pas. Sebenarnya itu mungkin yang paling cocok untuk jenis operasi ini.