Slicing array 1D

Slicing start:stop:step dan indeks negatif pada array satu dimensi.

Daftar isi

Slicing adalah pemilihan sebagian isi array berdasarkan rentang indeks, dan pada array satu dimensi seluruh kebutuhan itu dilayani oleh satu notasi, yaitu start:stop:step. Topik ini membahas notasi tersebut secara lengkap, mulai dari rentang dasar, langkah, indeks negatif, sampai satu perilaku penting yang sering terlewat, yaitu hasil slicing tetap terikat pada array asalnya. Setelah topik ini dibaca, rentang nilai pada array satu dimensi dapat dipilih dengan tepat dan sifat ikatan antara potongan dengan array asalnya sudah diketahui sebelum masuk ke perbandingan yang lebih rinci pada topik View versus salinan.

Notasi start:stop:step#

Notasi start:stop:step memilih elemen mulai indeks start sampai sebelum stop, dengan kenaikan step antar elemennya. Batas stop bersifat eksklusif, artinya elemen pada indeks stop tidak ikut diambil. Apabila start ditiadakan, pemilihan dimulai dari elemen pertama, apabila stop ditiadakan pemilihan berlanjut sampai elemen terakhir, dan apabila step ditiadakan kenaikannya bernilai satu.

Kode berikut menunjukkan tiga pemanggilan slicing pada array yang sama. Elemen bernilai 50 tidak muncul pada hasil a[1:4] karena 50 berada pada indeks 4, sedangkan batas stop berhenti sebelum indeks tersebut.

python Contoh: rentang dasar dengan start dan stop
import numpy as np

a = np.array([10, 20, 30, 40, 50, 60])
print(a[1:4])
print(a[:3])
print(a[3:])
text Keluaran
[20 30 40]
[10 20 30]
[40 50 60]

Hasil a[1:4] adalah [20 30 40] karena 20 berada pada indeks 1 dan 40 berada pada indeks 3. Bentuk a[:3] setara dengan a[0:3], sedangkan a[3:] mengambil semua elemen dari indeks 3 sampai akhir. Ketiga bentuk itu menghasilkan array baru dengan panjang yang dapat dihitung dari rumus stop - start ketika step bernilai satu, sehingga a[1:4] memuat 4 - 1 yaitu tiga elemen.

Argumen step mengatur lompatan pemilihan. Nilai step dua berarti mengambil satu elemen lalu melewati satu elemen, sedangkan nilai step negatif berarti pemilihan berjalan dari kanan ke kiri, dengan a[::-1] sebagai bentuk yang membalik seluruh urutan array.

python Contoh: langkah step dan pembalikan urutan
import numpy as np

a = np.array([10, 20, 30, 40, 50, 60])
print(a[::2])
print(a[1::2])
print(a[::-1])
text Keluaran
[10 30 50]
[20 40 60]
[60 50 40 30 20 10]

Indeks negatif dan langkah negatif#

Indeks negatif menghitung posisi dari akhir array, dengan -1 sebagai elemen terakhir dan -2 sebagai elemen di depannya. Penomoran ini berlaku baik pada indeks tunggal maupun pada batas start dan stop di dalam slicing, sehingga dua elemen terakhir cukup ditulis a[-2:] tanpa perlu menghitung panjang array terlebih dahulu.

python Contoh: indeks negatif pada batas slicing
import numpy as np

a = np.array([10, 20, 30, 40, 50, 60])
print(a[-2:])
print(a[-4:-1])
print(a[-1:-4:-1])
text Keluaran
[50 60]
[30 40 50]
[60 50 40]

Hasil a[-4:-1] adalah [30 40 50] karena indeks -4 menunjuk nilai 30 dan indeks -1 menunjuk nilai 60 yang tidak ikut diambil. Sifat eksklusif batas stop tetap berlaku ketika kedua batas bernilai negatif. Pada bentuk a[-1:-4:-1], langkah negatif membuat pemilihan berjalan mundur dari indeks -1 sampai sebelum indeks -4, sehingga hasilnya [60 50 40]. Kombinasi indeks negatif dengan langkah negatif inilah yang menjadikan a[::-1] cara ringkas untuk membalik urutan array tanpa menulis perulangan.

Slice adalah view, bukan salinan#

Operasi slicing tidak menyalin data. Hasil slicing adalah view, yakni array yang menunjuk memori data array asalnya tanpa menyalin nilai apa pun, sehingga keduanya berbagi memori yang sama. Akibatnya, mengubah isi potongan ikut mengubah array asalnya. Fungsi np.shares_memory mengembalikan True bila dua array berbagi memori, dan nilai itu dapat digunakan untuk membuktikan ikatan tersebut.

python Contoh: potongan tetap terikat pada array asal
import numpy as np

a = np.array([10, 20, 30, 40, 50, 60])
potongan = a[1:4]
print(np.shares_memory(a, potongan))
potongan[0] = 99
print(a)
text Keluaran
True
[10 99 30 40 50 60]

Penugasan potongan[0] = 99 menulis pada memori yang sama dengan elemen indeks 1 milik a, sehingga nilai 20 pada array asal ikut berubah menjadi 99. Perilaku ini bukan cacat, melainkan desain yang menjaga pemotongan array berukuran besar tetap murah karena tidak ada salinan yang dibuat. Apabila data yang benar-benar independen diperlukan, panggil .copy() pada hasil slicing. Perbedaan view dan salinan, termasuk cara memeriksanya, dibahas lengkap pada topik View versus salinan.

Kesalahan umum#

  1. Menganggap batas stop ikut diambil. Pemanggilan a[1:4] sering dibaca sebagai “ambil elemen sampai indeks 4”, padahal elemen indeks 4 tidak termasuk. Perbaikannya adalah membaca stop sebagai tanda berhenti, sehingga elemen terakhir yang diambil berada pada indeks stop - 1.
  2. Mengira hasil slicing adalah salinan yang bebas. Mutasi pada potongan kemudian bocor ke array asal dan merusak data di tempat lain yang ikut membaca array tersebut. Perbaikannya adalah memanggil .copy() setiap kali potongan akan diubah.
  3. Mencampur perilaku indeks tunggal dengan slicing. Indeks tunggal di luar batas memunculkan error IndexError, sedangkan slicing yang melewati batas dibiarkan dan menghasilkan array yang lebih pendek, sehingga dua bentuk akses yang mirip memberikan perilaku yang berbeda.
python Contoh: indeks tunggal error, slicing melewati batas tetap berjalan
import numpy as np

a = np.array([10, 20, 30, 40, 50, 60])
try:
    print(a[10])
except IndexError as e:
    print(f"IndexError: {e}")
print(a[3:100])
text Keluaran
IndexError: index 10 is out of bounds for axis 0 with size 6
[40 50 60]

Keluaran di atas menunjukkan bahwa a[10] gagal karena panjang array hanya enam elemen, sedangkan a[3:100] tetap berjalan dan hanya menghasilkan [40 50 60]. Perbedaan ini perlu diperhitungkan ketika batas pemotongan berasal dari perhitungan lain, karena potongan yang terlalu lebar tidak memberi tahu bahwa batasnya keliru.

Ringkasan#

  • Notasi start:stop:step memilih elemen mulai start sampai sebelum stop dengan kenaikan step, dan batas stop tidak ikut diambil.
  • Indeks negatif menghitung posisi dari akhir array, sedangkan step negatif membalik arah pemilihan, dengan a[::-1] sebagai bentuk ringkas untuk membalik seluruh urutan.
  • Hasil slicing adalah view yang berbagi memori dengan array asal, sehingga mutasi pada potongan ikut mengubah data asal.
  • Panggil .copy() apabila potongan perlu dimodifikasi tanpa menyentuh array asalnya.

Referensi#