Transformasi Array

array_map, array_filter, dan array_reduce.

Daftar isi

Transformasi mengubah satu array menjadi array lain tanpa menuliskan perulangan manual. Topik ini membahas tiga fungsi utamanya, yaitu array_map() untuk mengubah setiap elemen, array_filter() untuk menyaring elemen, dan array_reduce() untuk menumpuk seluruh elemen menjadi satu nilai. Ketiganya menerima callback, yaitu fungsi yang dikirim sebagai argumen dan dipanggil untuk setiap elemen. Setelah membacanya, alur pengolahan data array dapat disusun dari ketiga fungsi tersebut dengan perilaku yang terukur.

array_map: mengubah setiap elemen#

Fungsi array_map() memanggil callback sekali untuk setiap elemen dan mengembalikan array baru berisi hasilnya, sedangkan array asal tidak berubah. Apabila tepat satu array dikirim, kunci array hasil mengikuti kunci array asalnya, termasuk kunci string. Apabila beberapa array dikirim sekaligus, callback menerima satu nilai dari setiap array pada posisi yang sama, dan kunci hasil disusun ulang menjadi berurutan.

Callback paling ringkas dituliskan sebagai arrow function, yaitu fungsi anonim satu ekspresi dengan kata kunci fn. Contoh berikut memetakan nilai ujian menjadi label kelulusan, lalu menggandakan seluruh jumlah stok pada array asosiatif.

php petakan-nilai.php
<?php

$nilaiUjian = [78, 85, 91];

$status = array_map(fn(int $nilai) => $nilai >= 80 ? 'lulus' : 'perbaikan', $nilaiUjian);

print_r($status);

$stok = ['kertas' => 120, 'spidol' => 45];

$gandaStok = array_map(fn(int $jumlah) => $jumlah * 2, $stok);

print_r($gandaStok);
text Keluaran
Array
(
    [0] => perbaikan
    [1] => lulus
    [2] => lulus
)
Array
(
    [kertas] => 240
    [spidol] => 90
)

Array hasil pertama memuat indeks 0 sampai 2 mengikuti kunci array asalnya, sedangkan array hasil kedua tetap memegang kunci 'kertas' dan 'spidol' karena hanya satu array yang dikirim pada setiap pemanggilan. Perubahan seperti ini dapat dibaca tanpa perulangan, dan array $nilaiUjian beserta $stok tidak ikut berubah.

array_filter: menyaring elemen#

Fungsi array_filter() mengembalikan array baru yang hanya memuat elemen yang lolos uji. Callback menerima satu elemen dan mengembalikan nilai kebenaran. Elemen dipertahankan apabila hasilnya bernilai benar. Kunci elemen yang lolos dipertahankan apa adanya, sehingga hasil saringan dapat memuat lubang kunci dan array_values() diperlukan apabila bentuk list yang padat diinginkan.

Apabila callback tidak dikirim, elemen yang bernilai salah seperti 0, null, dan string kosong dibuang. Parameter ketiga yang berisi ARRAY_FILTER_USE_KEY mengubah peran callback menjadi menerima kunci, bukan nilai, sehingga penyaringan berdasarkan nama kunci dapat dituliskan.

Contoh berikut menyaring siswa yang lulus berdasarkan nilainya, lalu menyaring isi array campuran tanpa callback.

php saring-nilai.php
<?php

$nilaiUjian = [
    'Ali'   => 78,
    'Budi'  => 65,
    'Citra' => 91,
    'Dewi'  => 55,
];

$lulus = array_filter($nilaiUjian, fn(int $nilai) => $nilai >= 70);

print_r($lulus);
print_r(array_values($lulus));

$campur = [10, 0, '20', null, 'teks'];

print_r(array_filter($campur));
text Keluaran
Array
(
    [Ali] => 78
    [Citra] => 91
)
Array
(
    [0] => 78
    [1] => 91
)
Array
(
    [0] => 10
    [2] => 20
    [4] => teks
)

Hasil saringan pertama mempertahankan kunci 'Ali' dan 'Citra' sesuai array asalnya, kemudian array_values() menyusunnya menjadi indeks 0 dan 1. Pada array campuran, nilai 0 dan null terbuang tanpa callback karena keduanya bernilai salah menurut PHP.

array_reduce: menumpuk menjadi satu nilai#

Fungsi array_reduce() mengunjungi elemen satu per satu dari kiri ke kanan sambil membawa nilai akumulasi yang disebut $carry. Callback menerima $carry beserta elemen saat itu dan mengembalikan $carry yang diperbarui, sehingga seluruh array pada akhirnya tertumpuk menjadi satu nilai. Parameter ketiga berupa nilai awal yang dipakai sebelum elemen pertama dibaca, dan pengisian parameter ini membuat hasil pada array kosong tetap terduga.

Contoh berikut menjumlahkan belanjaan, merangkai daftar menjadi satu string, lalu memperlihatkan perilaku array kosong dengan dan tanpa nilai awal.

php akumulasi-nilai.php
<?php

$belanjaan = [12000, 7500, 4300];

$total = array_reduce($belanjaan, fn(int $carry, int $harga) => $carry + $harga, 0);

echo "total belanja: $total\n";

$rangkuman = array_reduce(
    ['beras', 'telur', 'minyak'],
    fn(string $carry, string $item) => ($carry === '' ? '' : $carry . ', ') . $item,
    ''
);

echo "daftar: $rangkuman\n";

var_dump(array_reduce([], fn(int $carry, int $item) => $carry + $item));
var_dump(array_reduce([], fn(int $carry, int $item) => $carry + $item, 0));
text Keluaran
total belanja: 23800
daftar: beras, telur, minyak
NULL
int(0)

Pemanggilan tanpa nilai awal pada array kosong mengembalikan null, sedangkan pemanggilan dengan nilai awal 0 mengembalikan 0. Karena itu nilai awal dikirim setiap kali hasilnya akan dipakai dalam perhitungan.

Menyusun alur transformasi#

Ketiga fungsi dapat dirangkai karena keluaran satu fungsi menjadi masukan fungsi berikutnya. Alur yang lazim adalah menyaring data terlebih dahulu agar jumlah elemen berkurang, lalu memetakan bentuk datanya, dan menumpuk hasil pemetaan menjadi satu angka. Penulisan setiap tahap ke variabel berbeda membuat alur mudah dibaca dan mudah diperiksa dibandingkan penulisan bersarang dalam satu ekspresi.

Contoh berikut menghitung rata-rata selisih di atas 70 dari nilai ujian yang lulus, dengan tiga tahap yang disimpan pada variabel tersendiri.

php alur-transformasi.php
<?php

$nilaiUjian = [78, 65, 91, 55, 84, 72];

$lulus = array_filter($nilaiUjian, fn(int $nilai) => $nilai >= 70);

$selisih = array_map(fn(int $nilai) => $nilai - 70, $lulus);

$rataSelisih = array_reduce($selisih, fn(int $carry, int $s) => $carry + $s, 0) / count($selisih);

echo "jumlah lulus: ", count($lulus), "\n";
echo "rata-rata selisih di atas 70: ", $rataSelisih, "\n";
text Keluaran
jumlah lulus: 4
rata-rata selisih di atas 70: 11.25

Tahap penyaringan menyisakan empat nilai, tahap pemetaan mengubah nilai tersebut menjadi selisih terhadap 70, dan tahap akumulasi menjumlahkan seluruh selisih sebelum dibagi banyaknya elemen. Setiap tahap memiliki array atau nilai miliknya sendiri, sehingga kesalahan pada satu tahap dapat diperiksa tanpa membaca seluruh rantai.

Kesalahan umum#

  • Lupa array_values() setelah array_filter(). Kunci hasil saringan mengikuti array asal sehingga dapat berlubang, dan fungsi yang mengharapkan list padat memberikan hasil yang tidak terduga. Susun ulang kuncinya apabila bentuk list diperlukan.
  • Mengira array asal ikut berubah. Ketiga fungsi bekerja pada salinan dan mengembalikan hasil baru, sehingga tanpa penugasan hasilnya hilang. Simpan keluarannya ke variabel.
  • Memanggil array_reduce() tanpa nilai awal pada array kosong. Hasilnya null dan bukan 0, sehingga perhitungan berikutnya keliru. Kirim nilai awal setiap kali hasil dipakai dalam operasi aritmetika.
  • Menuliskan callback dengan jumlah parameter yang tidak cocok. array_map() dengan dua array memerlukan callback dua parameter, dan ketidakcocokannya memicu error argumen saat eksekusi.

Ringkasan#

  • array_map() mengubah setiap elemen menjadi nilai baru, dan kunci asal dipertahankan apabila hanya satu array yang dikirim.
  • array_filter() mempertahankan elemen yang lolos uji kebenaran dan mempertahankan kuncinya, sehingga hasilnya dapat berlubang.
  • array_reduce() menumpuk seluruh elemen menjadi satu nilai melalui $carry, dan nilai awalnya sebaiknya selalu dikirim.
  • Ketiganya mengembalikan hasil baru tanpa mengubah array asal, sehingga dapat dirangkai menjadi alur penyaringan, pemetaan, dan akumulasi.

Referensi#