Apa sebenarnya perbedaan antara array_map
, array_walk
dan array_filter
. Apa yang bisa saya lihat dari dokumentasi adalah bahwa Anda dapat melewati fungsi panggilan balik untuk melakukan suatu tindakan pada array yang disediakan. Tapi sepertinya saya tidak menemukan perbedaan khusus di antara mereka.
Apakah mereka melakukan hal yang sama?
Bisakah mereka digunakan secara bergantian?
Saya akan menghargai bantuan Anda dengan contoh ilustratif jika mereka berbeda sama sekali.
Jawaban:
array_map
tidak dapat mengubah nilai di dalam array input selagiarray_walk
bisa; khususnya,array_map
tidak pernah mengubah argumennya.array_map
tidak dapat beroperasi dengan kunci array,array_walk
bisa.array_map
mengembalikan array baru,array_walk
hanya mengembalikantrue
. Oleh karena itu, jika Anda tidak ingin membuat array sebagai akibat dari melintasi satu array, Anda harus menggunakanarray_walk
.array_map
juga dapat menerima jumlah array yang sewenang-wenang dan dapat beralih di atasnya secara paralel, sementaraarray_walk
hanya beroperasi pada satu array .array_walk
dapat menerima parameter arbitrer tambahan untuk diteruskan ke panggilan balik. Ini sebagian besar tidak relevan sejak PHP 5.3 (ketika fungsi anonim diperkenalkan).array_map
memiliki panjang yang sama dengan array input terbesar;array_walk
tidak mengembalikan array tetapi pada saat yang sama tidak dapat mengubah jumlah elemen array asli;array_filter
hanya mengambil subset elemen-elemen array sesuai dengan fungsi penyaringan. Itu mempertahankan kunci.Contoh:
Hasil:
sumber
array_map(callback($key, $value), array_keys($array), $array)
Gagasan pemetaan fungsi ke array data berasal dari pemrograman fungsional. Anda seharusnya tidak memikirkannya
array_map
sebagaiforeach
loop yang memanggil fungsi pada setiap elemen array (meskipun begitulah penerapannya). Itu harus dianggap sebagai menerapkan fungsi ke setiap elemen dalam array secara mandiri.Secara teori hal-hal seperti pemetaan fungsi dapat dilakukan secara paralel karena fungsi yang diterapkan pada data HANYA memengaruhi data dan BUKAN keadaan global. Ini karena seorang
array_map
dapat memilih urutan apa pun untuk menerapkan fungsi ke item dalam (meskipun dalam PHP tidak).array_walk
di sisi lain itu pendekatan yang berlawanan untuk menangani array data. Alih-alih menangani setiap item secara terpisah, ia menggunakan status (&$userdata
) dan dapat mengedit item di tempatnya (seperti loop foreach). Karena setiap kali item$funcname
menerapkannya, item tersebut dapat mengubah status global program dan karenanya memerlukan cara tunggal yang benar dalam memproses item.Kembali di tanah PHP,
array_map
danarray_walk
hampir identik kecualiarray_walk
memberi Anda lebih banyak kontrol atas iterasi data dan biasanya digunakan untuk "mengubah" data di tempat vs mengembalikan array "diubah" yang baru.array_filter
benar-benar sebuah aplikasi dariarray_walk
(atauarray_reduce
) dan lebih-kurang hanya disediakan untuk kenyamanan.sumber
array_filter()
bisa diterapkan menggunakanarray_walk()
?Dari dokumentasi,
array_walk mengambil array dan fungsi
F
dan memodifikasinya dengan mengganti setiap elemen x denganF(x)
.array_map melakukan hal yang sama persis kecuali bahwa alih-alih memodifikasi di tempat itu akan mengembalikan array baru dengan elemen yang diubah.
array_filter dengan fungsi
F
, alih-alih mengubah elemen, akan menghapus elemen apa pun yangF(x)
tidak benarsumber
array_walk
kembali array sepertiarray_map
dan menemukan masalah itu dalam fungsi saya. Tidak menyadari sampai saya melihat ini bahwa tipe kembalinya adalah boolean.Jawaban lain menunjukkan perbedaan antara array_walk (modifikasi di tempat) dan array_map (kembalikan salinan yang dimodifikasi) dengan cukup baik. Namun, mereka tidak benar-benar menyebutkan array_reduce, yang merupakan cara menerangi untuk memahami array_map dan array_filter.
Fungsi array_reduce mengambil array, fungsi dua argumen dan 'akumulator', seperti ini:
Elemen array dikombinasikan dengan akumulator satu per satu, menggunakan fungsi yang diberikan. Hasil dari panggilan di atas sama dengan melakukan ini:
Jika Anda lebih suka berpikir dalam hal loop, itu seperti melakukan yang berikut (Saya sebenarnya menggunakan ini sebagai fallback ketika array_reduce tidak tersedia):
Versi perulangan ini menjelaskan mengapa saya menyebut argumen ketiga sebagai 'akumulator': kita dapat menggunakannya untuk mengumpulkan hasil melalui setiap iterasi.
Jadi apa hubungannya dengan array_map dan array_filter? Ternyata mereka berdua jenis array_reduce tertentu. Kita bisa menerapkannya seperti ini:
Abaikan fakta bahwa array_map dan array_filter mengambil argumen mereka dalam urutan yang berbeda; itu hanyalah kekhasan dari PHP. Poin penting adalah bahwa sisi kanan identik kecuali untuk fungsi yang saya sebut $ MAP dan $ FILTER. Jadi, seperti apa mereka?
Seperti yang Anda lihat, kedua fungsi menerima $ akumulator dan mengembalikannya lagi. Ada dua perbedaan dalam fungsi-fungsi ini:
Perhatikan bahwa ini jauh dari hal-hal sepele yang tidak berguna; kita dapat menggunakannya untuk membuat algoritma kita lebih efisien!
Kita sering dapat melihat kode seperti dua contoh ini:
Menggunakan array_map dan array_filter bukan loop membuat contoh-contoh ini terlihat cukup bagus. Namun, bisa jadi sangat tidak efisien jika $ input besar, karena panggilan pertama (peta atau filter) akan melintasi $ input dan membangun array perantara. Array perantara ini diteruskan langsung ke panggilan kedua, yang akan melintasi semuanya lagi, maka array perantara perlu dikumpulkan dari sampah.
Kita dapat menyingkirkan array perantara ini dengan mengeksploitasi fakta bahwa array_map dan array_filter adalah contoh dari array_reduce. Dengan menggabungkan mereka, kita hanya perlu menelusuri $ input sekali dalam setiap contoh:
CATATAN: Implementasi saya array_map dan array_filter di atas tidak akan berperilaku persis seperti PHP, karena array_map saya hanya dapat menangani satu array pada suatu waktu dan array_filter saya tidak akan menggunakan "kosong" sebagai fungsi $ default. Juga, tidak ada yang akan menyimpan kunci.
Tidak sulit untuk membuat mereka berperilaku seperti PHP, tetapi saya merasa bahwa komplikasi ini akan membuat ide inti lebih sulit dikenali.
sumber
Revisi berikut berusaha untuk menggambarkan dengan lebih jelas PHP's array_filer (), array_map (), dan array_walk (), yang semuanya berasal dari pemrograman fungsional:
array_filter () memfilter data, menghasilkan array baru yang hanya menahan item yang diinginkan dari array sebelumnya, sebagai berikut:
kode langsung di sini
Semua nilai numerik disaring dari $ array, meninggalkan $ difilter dengan hanya jenis buah.
array_map () juga membuat array baru tetapi tidak seperti array_filter () array yang dihasilkan berisi setiap elemen dari input $ filter tetapi dengan nilai yang diubah, karena menerapkan callback ke setiap elemen, sebagai berikut:
kode langsung di sini
Kode dalam hal ini berlaku panggilan balik menggunakan strtoupper built-in () tetapi fungsi yang ditentukan pengguna juga merupakan pilihan lain yang layak. Callback berlaku untuk setiap item $ filtered dan karenanya menghasilkan $ nu yang elemennya mengandung nilai huruf besar.
Dalam cuplikan berikutnya, array walk () melintasi $ nu dan membuat perubahan pada setiap elemen vis a vis operator referensi '&'. Perubahan terjadi tanpa membuat array tambahan. Nilai setiap elemen berubah di tempatnya menjadi string yang lebih informatif yang menentukan kunci, kategori, dan nilainya.
Lihat demo
Catatan: fungsi callback sehubungan dengan array_walk () mengambil dua parameter yang secara otomatis akan memperoleh nilai elemen dan kunci dan dalam urutan itu, juga ketika dipanggil oleh array_walk (). (Lihat lebih lanjut di sini ).
sumber
$lambda
dan$callback
hanya ekspansi eta dari fungsi yang ada, dan karenanya sepenuhnya berlebihan. Anda bisa mendapatkan hasil yang sama dengan melewati (nama) fungsi yang mendasarinya:$filtered = array_filter($array, 'ctype_alpha');
dan$nu = array_map('strtoupper', $filtered);