Data yang tersimpan di array jarang langsung siap dipakai. Kita sering perlu mengubah setiap elemen (misalnya menerapkan diskon pada semua harga), membuang elemen yang tidak relevan, lalu merangkum sisanya menjadi satu angka atau satu string. Tiga fungsi bawaan PHP — array_map, array_filter, dan array_reduce — menuntaskan ketiga tugas tersebut tanpa loop manual. Chapter ini membahas pemakaian praktis ketiganya untuk membentuk data (data shaping), termasuk aturan penting tentang kunci array yang sering menjebak pemula.

Transformasi Setiap Elemen dengan array_map #

array_map menerapkan sebuah callback — fungsi kecil yang dikirim sebagai argumen ke fungsi lain — pada setiap nilai di dalam array, lalu mengembalikan array baru berisi hasil-hasil transformasi tersebut. Array sumber sama sekali tidak berubah. Bentuk fn (int $h): int => ... pada contoh berikut adalah arrow function, sintaks ringkas PHP untuk fungsi satu ekspresi.

php
<?php
$harga = [10000, 25000, 5000];

$hargaDiskon = array_map(
    fn (int $h): int => intdiv($h * 90, 100),
    $harga
);

print_r($hargaDiskon);

Output yang Dihasilkan:

text
Array
(
    [0] => 9000
    [1] => 22500
    [2] => 4500
)

Mari kita telaah apa yang terjadi pada kode di atas:

  1. Baris 2 ($harga = ...): array sumber berisi tiga harga dalam rupiah.
  2. Baris 4–5 (callback): callback menerima satu harga, mengalikannya dengan 90, lalu membaginya dengan 100 memakai intdiv — setara diskon 10% tanpa risiko pembulatan float.
  3. Baris 3–6 (array_map(...)): fungsi memanggil callback untuk ketiga harga lalu menyusun hasilnya ke array baru $hargaDiskon, sementara $harga tetap memuat nilai asli.

Aturan Kunci pada array_map #

Kunci array hanya dipertahankan oleh array_map apabila tepat satu array yang dikirim. Ketika callback menerima nilai dari dua array atau lebih, array hasil selalu diindeks ulang secara numerik mulai dari nol. Perhatikan perbedaan pada dua pemanggilan berikut:

php
<?php
$stok = ['apel' => 10, 'jeruk' => 8, 'mangga' => 12];

// Satu array: kunci string tetap dipertahankan
$stokBaru = array_map(fn (int $s): int => $s + 5, $stok);
print_r($stokBaru);

// Dua array: kunci hasil diindeks ulang secara numerik
$nama = ['Budi', 'Siti'];
$nilai = [80, 95];
$pasangan = array_map(
    fn (string $n, int $v): string => "$n: $v",
    $nama,
    $nilai
);
print_r($pasangan);

Output yang Dihasilkan:

text
Array
(
    [apel] => 15
    [jeruk] => 13
    [mangga] => 17
)
Array
(
    [0] => Budi: 80
    [1] => Siti: 95
)

Pada pemanggilan pertama, kunci apel, jeruk, dan mangga ikut terbawa ke hasil. Pada pemanggilan kedua, callback menerima dua nilai sekaligus (satu dari $nama, satu dari $nilai), sehingga hasilnya menjadi array berindeks 0 dan 1. Bila panjang array berbeda, array yang lebih pendek diisi null agar callback tetap dipanggil — deklarasikan parameter callback sebagai nullable (misalnya ?string) bila Anda memakai pola ini.

Trik lain yang berguna: mengirim null sebagai callback menjadikan array_map sebagai zipper yang menggabungkan beberapa array menjadi array berisi pasangan nilai:

php
<?php
$nama = ['Budi', 'Siti', 'Andi'];
$nilai = [80, 95, 70];

$pasangan = array_map(null, $nama, $nilai);
print_r($pasangan);

Output yang Dihasilkan:

text
Array
(
    [0] => Array
        (
            [0] => Budi
            [1] => 80
        )

    [1] => Array
        (
            [0] => Siti
            [1] => 95
        )

    [2] => Array
        (
            [0] => Andi
            [1] => 70
        )

)

Setiap elemen hasil adalah array kecil yang menampung satu nilai dari $nama dan satu nilai dari $nilai pada posisi yang sama. Pola ini praktis saat Anda ingin mengolah beberapa kolom data secara paralel.

Menyaring Elemen dengan array_filter #

array_filter menjalankan callback untuk setiap elemen dan hanya mempertahankan elemen yang callback-nya mengembalikan nilai truthy. Elemen lain dibuang dari hasil, tetapi array aslinya tetap utuh. Berbeda dengan array_map, kunci array hasil array_filter selalu dipertahankan apa adanya.

php
<?php
$nilai = [80, 45, 95, 60, 30];

$lulus = array_filter($nilai, fn (int $n): bool => $n >= 60);
print_r($lulus);

$urut = array_values($lulus);
print_r($urut);

Output yang Dihasilkan:

text
Array
(
    [0] => 80
    [2] => 95
    [3] => 60
)
Array
(
    [0] => 80
    [1] => 95
    [2] => 60
)

Nilai 45 dan 30 gagal melewati syarat sehingga dibuang, dan kunci 1 serta 4 ikut hilang bersama nilai tersebut — kunci 0, 2, 3 tetap ada di hasil. Panggilan array_values() kemudian merapikan hasil menjadi list berindeks berurutan 0, 1, 2.

Menyaring Tanpa Callback dan Berdasarkan Kunci #

Tanpa callback, array_filter membuang semua nilai falsy — 0, 0.0, '', '0', null, false, dan array kosong. Flag ARRAY_FILTER_USE_KEY membuat callback menerima kunci, bukan nilai:

php
<?php
$campuran = [0, 'Budi', '', null, 42, false, 'Siti'];
print_r(array_filter($campuran));

$produk = ['apel' => 5000, 'jeruk' => 8000, 'mangga' => 12000];
$namaPanjang = array_filter(
    $produk,
    fn (string $k): bool => strlen($k) > 5,
    ARRAY_FILTER_USE_KEY
);
print_r($namaPanjang);

Output yang Dihasilkan:

text
Array
(
    [1] => Budi
    [4] => 42
    [6] => Siti
)
Array
(
    [mangga] => 12000
)

Pada pemanggilan pertama, hanya 'Budi', 42, dan 'Siti' yang bertahan karena nilai lain falsy. Pada pemanggilan kedua, hanya mangga (enam huruf) yang kuncinya lebih panjang dari lima karakter. PHP juga menyediakan flag ARRAY_FILTER_USE_BOTH bila callback perlu menerima nilai sekaligus kunci.

Merangkum Nilai dengan array_reduce #

array_reduce melipat (fold) seluruh elemen menjadi satu nilai tunggal. Callback menerima dua parameter: $carry (akumulator yang terus terbawa) dan $item (elemen saat ini). Argumen ketiga adalah nilai awal akumulator — dan menjadi hasil akhir bila array-nya kosong.

php
<?php
$keranjang = [
    ['nama' => 'Apel', 'harga' => 5000, 'jumlah' => 3],
    ['nama' => 'Jeruk', 'harga' => 8000, 'jumlah' => 2],
    ['nama' => 'Mangga', 'harga' => 12000, 'jumlah' => 1],
];

$total = array_reduce(
    $keranjang,
    fn (int $carry, array $item): int => $carry + $item['harga'] * $item['jumlah'],
    0
);

echo "Total belanja: Rp$total\n";

Output yang Dihasilkan:

text
Total belanja: Rp43000

Beginilah perjalanan akumulatornya:

  1. Awal: $carry diisi nilai awal 0.
  2. Langkah 1 (Apel): 0 + 5000 × 3 = 15000, tersimpan kembali ke $carry.
  3. Langkah 2 (Jeruk): 15000 + 8000 × 2 = 31000.
  4. Langkah 3 (Mangga): 31000 + 12000 × 1 = 43000 — nilai inilah yang dikembalikan.

Selalu berikan nilai awal secara eksplisit. Tanpa argumen ketiga, akumulator pertama berisi null, yang memicu peringatan pada operasi aritmetika dan membuat tipe hasil sulit diprediksi.

Menyusun Pipeline Map–Filter–Reduce #

Kekuatan sebenarnya muncul ketiganya dirangkai menjadi satu pipeline. Kode berikut menambah biaya kirim Rp10.000 pada setiap pesanan, menyaring pesanan bernilai besar, lalu menjumlahkannya:

php
<?php
$pesanan = [
    ['nama' => 'Budi', 'total' => 75000],
    ['nama' => 'Siti', 'total' => 250000],
    ['nama' => 'Andi', 'total' => 150000],
];

$grand = array_reduce(
    array_filter(
        array_map(
            fn (array $p): array => ['nama' => $p['nama'], 'total' => $p['total'] + 10000],
            $pesanan
        ),
        fn (array $p): bool => $p['total'] >= 150000
    ),
    fn (int $carry, array $p): int => $carry + $p['total'],
    0
);

echo "Grand total: Rp$grand\n";

Output yang Dihasilkan:

text
Grand total: Rp420000

Alurnya terbaca dari dalam ke luar:

  1. array_map menambahkan biaya kirim 10000 pada setiap pesanan: 85000, 260000, 160000.
  2. array_filter hanya menyisakan pesanan bersyarat >= 150000: 260000 dan 160000.
  3. array_reduce menjumlahkan sisanya: 260000 + 160000 = 420000.

Perbandingan Perilaku Kunci #

Ketiga fungsi ini sering dipakai bergantian, jadi rangkuman berikut layak diingat:

FungsiTugas utamaKunci array hasil
array_mapmengubah setiap nilaidipertahankan hanya bila tepat satu array dikirim
array_filtermenyaring elemenselalu dipertahankan apa adanya
array_reducemelipat seluruh elemen menjadi satu nilaitidak menghasilkan array

Untuk pencarian satu nilai tunggal seperti in_array atau array_search, Chapter Searching dan Filtering Arrays sudah membahasnya terpisah.

Ringkasan #

array_map mengubah nilai, array_filter menyaring elemen, dan array_reduce merangkum semuanya menjadi satu hasil — ketiganya bekerja pada salinan dan tidak mengubah array sumber. Aturan kunci yang perlu diingat: array_map menjaga kunci hanya untuk satu array, sedangkan array_filter selalu menjaga kunci sehingga array_values() sering diperlukan. Perspektif pemrograman fungsional atas pola ini — imutabilitas dan komposisi fungsi — akan kita dalami di Chapter array_map, array_filter, dan array_reduce pada Section Functional Programming . Selanjutnya, kita membahas cara menggabungkan dan membandingkan dua array sekaligus lewat operasi merge dan difference.

Referensi #